如何使用 FieldDefs 在运行时创建新的 SQLite 文件和 table?

How can I create a new SQLite file and table at runtime using FieldDefs?

我正在使用 Delphi Seattle 在全新的 SQLite 文件中创建一个全新的 table,并且仅使用 FieldDef 和非可视化代码。我可以使用 ExecSQL ('CREATE TABLE....' ) 语法创建一个 table 但不是如下所示(我得到 'No such table 'MyTable' 这是在我执行 CreateDataSet 调用时引发的).我想要一些允许我使用 FieldDefs 的解决方案。此代码以示例 here 为蓝本。不过我注意到,有关 CreateDataSet 的注释仅适用于 TFDMemTable。是否有一种运行时方法可以在不使用 ExecSQL 的情况下创建 SQLite table?

procedure Test;
const
  MyDBFile = 'c:\scratch\hope.db';
var
  Connection : TFDConnection;
  DriverLink : TFDPhysSQLiteDriverLink;
  Table : TFDTable;
begin
  DeleteFile( MyDBFile );
  DriverLink := TFDPhysSQLiteDriverLink.Create( nil );
  Connection := TFDConnection.Create( nil );
  try
    Connection.Params.Values['DriverID'] := 'SQLite';
    Connection.Params.Values['Database'] := MyDBFile;
    Connection.Connected := True;

    Table := TFDTable.Create( nil );
    try
      Table.TableName := 'MyTable';
      Table.Connection := Connection;
      Table.FieldDefs.Add( 'one', ftString, 20 );
      Table.FieldDefs.Add( 'two', ftString, 20 );
      Table.CreateDataSet;

      // I would add records here....
    finally
      Table.Free;
    end;
  finally
    Connection.Free;
    DriverLink.Free;
  end;
end;

CreateDataSet 通常是一个本地操作,用于将客户端数据集初始化为空状态。如果 TClientDataSet 是任何东西,afaik 它不能用于创建服务器端 table。

要创建一个实际的服务器 table,我希望必须构建 DDL SQL 来创建 table,然后使用 ExecSQL 执行它(客户端)数据集,正如您已经尝试过的那样。

更新

尽管使用了不显示 FieldDef 的 TFDTable 组件,以下内容似乎可以满足您在代码中完成所有操作的要求,因此我使用了代码创建的 TFields。在西雅图 D10 测试。

procedure TForm3.CreateDatabaseAndTable;
const
  DBName = 'd:\delphi\code\sqlite\atest.sqlite';
var
  AField : TField;
begin
  if FileExists(DBName) then
    DeleteFile(DBName);

  AField := TLargeIntField.Create(Self);
  AField.Name := 'IDField';
  AField.FieldName := 'ID';
  AField.DataSet := FDTable1;

  AField := TWideStringField.Create(Self);
  AField.Size := 80;
  AField.Name := 'NameField';
  AField.FieldName := 'Name';
  AField.DataSet := FDTable1;

  FDConnection1.Params.Values['database'] := DBName;
  FDConnection1.Connected:= True;

  FDTable1.TableName := 'MyTable';
  FDTable1.CreateTable(False, [tpTable]);
  FDTable1.Open();
  FDTable1.InsertRecord([1, 'First']);
  FDConnection1.Commit;


  FDConnection1.Connected:= False;
end;

我希望比我更熟悉的人可以使用 TFDMemTable 的 FieldDefs 做类似的事情,如果它通过 FDTableAdaptor 正确连接到服务器端组件(FDCommand?)。

顺便说一句,我使用了 LargeInt ID 字段和 WideString Name 字段,因为前一段时间尝试将 Sqlite 与 D7 一起使用时,我在尝试使用整数和字符串字段时遇到了无穷无尽的麻烦。

顺便说一句,如果您在部署之前知道所需的结构,您可能会发现如果您只是将一个空数据库 + table 复制到位,您可能会获得更多 predictable/robust 结果,而不是而不是尝试在原位创建 table 。 Ymmv,当然。

我永远不会梦想使用 fielddef 创建数据库 table,因为您最终会得到 table,但没有适当的主键、索引和引用完整性。结果 table 完全是 "dumbed down".

只要您在查询中有 "where" 子句,数据库就会进行完整的 table 扫描以查找与查询匹配的记录。所以你的数据库随着大小的增加而变慢(并且 CPU 使用增加)。那只是糟糕的设计。

此致, 亚瑟

您可以使用应用程序 SQLite Expert Professional,创建 SQLite 数据库。

并使用 FDConnection 连接到数据库。并使用它。 数据库SQLite的方法,和MartynA说的一样。

Begin
  FDConnection1.Connected:=false;
  FDConnection1.Params.Clear;
  FDConnection1.Params.Database:='D:\SQLiteDatabase.db';
  FDConnection1.ConnectionDefName:='SQLite_Demo';
  FDConnection1.DriverName:='SQLite';
  FDConnection1.Connected:=true;
  FDTable1.Open;
End;