带有 MS Access 2010 数据库的 Delphi FireDAC。为啥它将 ACE 转换为 Jet?

Posted

技术标签:

【中文标题】带有 MS Access 2010 数据库的 Delphi FireDAC。为啥它将 ACE 转换为 Jet?【英文标题】:Delphi FireDAC with MS Access 2010 database. Why does it convert ACE to Jet?带有 MS Access 2010 数据库的 Delphi FireDAC。为什么它将 ACE 转换为 Jet? 【发布时间】:2015-11-19 11:11:32 【问题描述】:

我已按照以下步骤将 .mdb 数据库转换为 .accdb 数据库: https://support.office.com/en-us/article/Convert-a-database-to-the-accdb-file-format-69abbf06-8401-4cf3-b950-f790fa9f359c (使用 MS Access 2010)

转换后,.accdb 文件以以下内容开头: (database.accdb,用十六进制编辑器查看的文件头),这正是我想要的......

00 01 00 00 53 74 61 6E 64 61 72 64 20 41 43 45 20 44 42 00 02 00 00 00 B5 6E 03 62 60 09 C2 55 E9 A9 67 72 40 3F 00 9C 7E 9F 90 FF 85 9A 31 C5
....Standard ACE DB.....µn.b`.ÂUé©gr@?.œ~Ÿ.ÿ…š1Å

打开数据库后,删除表,重新创建表并使用 TFDConnection / TFDPhysMSAccessDriverLink / TFDBatchMove / TFDBatchMoveDataSetReader / TFDBatchMoveDataSetWriter 和以下代码进行一些插入

  FAccessDB := TFDConnection.Create(Self);
  FAccessDB.Name := '';
  FAccessDB.Params.Clear;
  FAccessDB.Params.Add('DriverID=MSAcc_Direct');
  FAccessDB.LoginPrompt := False;

  // FDPhysMSAccessDriverLink1
  FFDPhysMSAccessDriverLink1 := TFDPhysMSAccessDriverLink.Create(Self);
  FFDPhysMSAccessDriverLink1.Name := '';
  FFDPhysMSAccessDriverLink1.DriverID := 'MSAcc_Direct';

  // Table_Out
  FFDTable_Out := TFDTable.Create(Self);
  FFDTable_Out.Name := '';
  FFDTable_Out.Connection := FAccessDB;

  // FDBatchMove1
  FFDBatchMove1 := TFDBatchMove.Create(Self);
  FFDBatchMove1.Name := '';
  FFDBatchMove1.OnError := FDBatchMove1Error;
  FFDBatchMove1.OnFindDestRecord := FDBatchMove1FindDestRecord;
  FFDBatchMove1.OnProgress := FDBatchMove1Progress;

  // FDBatchMoveDataSetReader1
  FFDBatchMoveDataSetReader1 := TFDBatchMoveDataSetReader.Create(Self);
  FFDBatchMoveDataSetReader1.Name := '';

  // FDBatchMoveDataSetWriter1
  FFDBatchMoveDataSetWriter1 := TFDBatchMoveDataSetWriter.Create(Self);
  FFDBatchMoveDataSetWriter1.Name := '';

  // FDBatchMove1
  FFDBatchMove1.Reader := FFDBatchMoveDataSetReader1;
  FFDBatchMove1.Writer := FFDBatchMoveDataSetWriter1;
  FFDBatchMove1.Options := [poIdentityInsert];

  FAccessDB.Params.Values['Database'] := 'database.accdb';
  FAccessDB.Connected := True;
  aDropTableSQL := 'DROP TABLE ' + FTablenameDest;
  FAccessDB.ExecSQL(aDropTableSQL);
  FAccessDB.Commit;
  aCreateTableSQL := 'CREATE TABLE ' + FTablenameDest; // plus the rest 
                                              //of the create statement

  FFDTable_Out.TableName := FTablenameDest;
  FFDTable_Out.Active := True;
  FFDBatchMoveDataSetReader1.DataSet := FDataSetSrc; // a TDataset from 
                                                       // another database 
  FFDBatchMoveDataSetWriter1.DataSet := FFDTable_Out;
  FFDBatchMoveDataSetWriter1.Direct := True;

  FFDBatchMoveDataSetReader1.DataSet.Active := True;
  FFDBatchMoveDataSetWriter1.DataSet.Active := True;

  FFDBatchMove1.Mode := dmAlwaysInsert;
  FFDBatchMove1.Execute;
  FAccessDB.Commit;
  FAccessDB.Connected := False;

  FFDMSAccessService1 := TFDMSAccessService.Create(Self);
  FFDMSAccessService1.Name := '';

  FFDMSAccessService1.Database := 'database.accdb';
  FFDMSAccessService1.DestDatabase := 'database.accdb_temp.accdb';

  FFDMSAccessService1.DBVersion := avAccess2007;

  FFDMSAccessService1.Compact;   // <-- seems to convert here...

database.accdb的文件头变成

00 01 00 00 53 74 61 6E 64 61 72 64 20 4A 65 74 20 44 42 00 01 00 00 00 B5 6E 03 62 60 09 C2 55 E9 A9 67 72 40 3F 00 9C 7E 9F 90 FF 85 9A 31 C5
....Standard Jet DB.....µn.b`.ÂUé©gr@?.œ~Ÿ.ÿ…š1Å

同样,在从 .mdb 转换为 .accdb 之前也是如此

在我看来,“标准 Jet DB”是指旧格式 (.mdb) 而“标准 ACE DB”意味着新格式 (.accdb)

FireDAC 会将其转换回来吗?为什么? 如何保留新的访问格式(.accdb、ACE DB)?

【问题讨论】:

“MSAcc_Direct”是 FireDAC 的第三方驱动程序,可直接操作 Access 数据库文件吗? FireDAC 文档here 仅提及使用 Access ODBC 的“MSAcc”。 不,它只是驱动程序链接组件的驱动程序 ID,我创建了名为 FFDPhysMSAccessDriverLink1(参见上面的代码),驱动程序 ID 为 := 'MSAcc_Direct'。它不是第三方驱动程序...我可以省略该组件而只写“MSAcc”。有时我使用驱动链接组件进行特殊设置...这里我使用默认设置。 同时,我发现了一个后备:我会用 FFDMSAccessService1.Compact 注释掉这些行;并使用 msaccess.exe 命令行:MSACCESS.EXE database.accdb /compact 但是:有更好的(程序化)解决方案吗? 【参考方案1】:

刚刚收到 Embarcadero 的回复(非常快的回复,酷!):

德米特里·阿雷菲耶夫写道: 这是一个已知的问题。目前 TFDMSAccessService 并不真正支持 avAccess2007。

--

谨此致以最诚挚的问候, Dmitry Arefiev / FireDAC 架构师

【讨论】:

有什么新消息吗?

以上是关于带有 MS Access 2010 数据库的 Delphi FireDAC。为啥它将 ACE 转换为 Jet?的主要内容,如果未能解决你的问题,请参考以下文章

带有 Like 语句的 MS-Access 上的 SQL 请求似乎永远无法正常工作

如何在 MS Access 2010 中使用 VBA 选择多值组合框的值?

带有“返回记录:否”的 MS Access 直通查询截断 ODBC 连接字符串

ms-access 2003:表单打不开!帮助!

将分隔文件 (.csv) 中的行导入 MS-Access 表

使用 c# 和 oledb 查询更新 Ms-Access 2010 中的列值