首页 > 解决方案 > delphi fireac sqlite 提交

问题描述

当我提交时,我天真地认为数据库的物理文件会被更新(更改修改日期),但显然它不是那样工作的。关闭数据库时修改了数据库的物理文件!!!

我用 (delphi 10.2.3) * FDConnection1: TFDConnection; 写了一个小测试应用程序。(所有默认设置) (cachedupdate 为 false) * FDQuery1: TFDQuery; (所有默认设置)

我的 SQLite 数据库只有一个表 CREATE TABLE t_stritems( IdItelsINTEGER, St01VARCHAR (200), St02VARCHAR (200), St03VARCHAR (200), PRIMARY KEY( IdItels) )

我的代码很简单

连接数据库:

  FDConnection1.Connected := false;
  FDConnection1.Params.Clear;
  FDConnection1.Params.Add('DriverID=SQLite');
  FDConnection1.Params.ADD('Database=' + Edit1.text);
  FDConnection1.Connected := true;

将行插入数据库

FDQuery1.Connection := FDConnection1;
FDQuery1.close;
fdquery1.sql.clear;
fdquery1.sql.add('DELETE FROM t_stritems');

FDConnection1.StartTransaction;
fdquery1.ExecSQL;
FDConnection1.Commit;

fdquery1.sql.clear;
fdquery1.sql.add('SELECT * FROM t_stritems');
fdquery1.Open;
for i := 0 to 15 do
  begin
    for j:= 1 to 2000 do
      begin
        FDQuery1.append;
        FDQuery1.FieldByname('IdItels').asInteger := (i*2000) + j;
        FDQuery1.FieldByname('St01').asString := 'Text 01 Number : ' + FDQuery1.FieldByname('IdItels').asString;
        FDQuery1.FieldByname('St02').asString := 'Text 02 Number : ' + FDQuery1.FieldByname('IdItels').asString;
        FDQuery1.FieldByname('St03').asString := 'Text 03 Number : ' + FDQuery1.FieldByname('IdItels').asString;
        FDQuery1.post;
      end;
//    FDConnection1.Commit;
  end;
end;

测试过程:连接数据库:(我的数据库的t_stritems文件包含32000条记录;数据库文件的大小是2338 ko)删除sql后,我的数据库文件目录中有一个日志文件(xxxx.db-杂志)。第一次提交后数据库文件大小为 2338 ko,我的数据库文件目录中始终有日志文件(xxxx.db-journal)。数据库文件大小为 2338 ko(无物理更新) 然后程序添加 32000 条记录 数据库文件(.db)的修改日期只有在我离开我的应用程序时才会被修改。!!!日志文件(.db-log)将在我的应用程序结束时被删除

问题:如何让commit将数据保存到数据库?这是正常的吗?数据库的物理文件仅在应用程序关闭时(以及连接的同时)被修改?

提前感谢您的回答最好的问候Romuald

标签: sqlitedelphicommitfiredac

解决方案


您似乎对如何在 Delphi 中使用数据库感到困惑。

1)首先,您需要在代码中添加 try/finally 以捕获任何异常并防止内存泄漏。

2) 使用 connection.StartTransaction - connection.Commit 配对。

3) 提交必须在循环结束时使用。当您完成更新数据时,调用 Commit 来执行您对字段所做的所有更新。

以下是我将如何重写您的代码以实现我上面的建议:

  FDConnection1.Connected := false;
  FDConnection1.Params.Clear;
  FDConnection1.Params.Add('DriverID=SQLite');
  FDConnection1.Params.Add('Database=' + 'Edit1.text');
  FDConnection1.Connected := true;
  FDQuery1.Connection := FDConnection1;
  // your first transaction
  // just use ExceSQL directly to run your SQL query
  FDQuery1.ExecSQL('DELETE FROM t_stritems');
  try
    // start your transaction and use query.Open()
    FDConnection1.StartTransaction;
    FDQuery1.Open('SELECT * FROM t_stritems');
    for i := 0 to 15 do
      begin
        for j := 1 to 2000 do
          begin
            FDQuery1.FieldByName('IdItels').asInteger := (i * 2000) + j;
            FDQuery1.FieldByName('St01').AsString := 'Text 01 Number : ' + FDQuery1.FieldByName('IdItels').AsString;
            FDQuery1.FieldByName('St02').AsString := 'Text 02 Number : ' + FDQuery1.FieldByName('IdItels').AsString;
            FDQuery1.FieldByName('St03').AsString := 'Text 03 Number : ' + FDQuery1.FieldByName('IdItels').AsString;
            FDQuery1.Post();
          end;
        // Dont use Commit inside loop. You should call Commit after you loop logic
        // FDConnection1.Commit;
      end;
    FDConnection1.Commit;
  finally
    FDConnection1.Close();
    FDQuery1.Free();
    FDConnection1.Free();
  end;

推荐阅读