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

j9per5c4  于 2023-10-18  发布在  SQLite
关注(0)|答案(4)|浏览(159)

我使用 Delphi 西雅图在一个全新的SQLite文件中创建一个全新的表,并且只使用FieldDefs和非可视化代码。我可以使用ExecSQL('CREATETABLE....')语法创建一个表,但不像下面所示的那样(我得到'No such table 'MyTable',这是在我执行SQL数据集调用时引发的)。我想一些解决方案,让我与FieldDefs的工作。这段代码是以here为例建模的。不过,我注意到,有一个关于TFDMem数据集的说明,它只适用于TFDMemTable。有没有一种运行时方法可以在不使用ExecSQL的情况下创建SQLite表?

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;
5ktev3wc

5ktev3wc1#

DataSet通常是一个本地操作,用于将客户端数据集初始化为空状态。如果TClientDataSet是什么去,afaik它不能用来创建一个服务器端表。
要创建一个实际的服务器表,我希望必须构造SQL来创建表,然后在(客户端)数据集上使用ExecSQL执行它,正如您已经尝试过的那样。

更新

下面的代码似乎可以满足您的要求,即用代码来完成所有工作,但使用的是TFDTable组件,而TFDTable组件并没有显示FieldDefs,因此我使用了代码创建的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(如果它正确连接到服务器端组件(FDCommand?)通过FDTableAdaptor。
Fwiw,我使用了LargeInt ID字段和WideString Name字段,因为前一段时间我试图在D 7中使用Sqlite,我在尝试使用String和String字段时遇到了很多麻烦。
顺便说一句,如果你在部署之前就知道你需要的结构,你可能会发现,如果你只是简单地复制一个空的数据库+表到适当的位置,而不是尝试在原地创建表,你会得到更可预测/健壮的结果。YMMV,当然。

mlnl4t2r

mlnl4t2r2#

我从来没有梦想过使用fielddef创建数据库表,因为你最终会得到没有合适的主键、索引和引用完整性的表。生成的表完全是“dumbed down”。
只要查询中有“where”子句,数据库就会进行全表扫描,以查找与查询匹配的记录。因此,数据库的速度会随着大小的增加而减慢(CPU的使用也会增加)。这只是糟糕的设计。
你好,亚瑟

v8wbuo2f

v8wbuo2f3#

您可以使用应用程序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;
oxosxuxt

oxosxuxt4#

我更喜欢用SQL命令创建表,你可以同时创建键、索引和约束

  • MartynA* 的代码在这里:
const
  DBName = 'atest.sqlite';
var
  AField : TField;
begin
  FDConnection1.Connected:= False;

  if FileExists(DBName) then
    DeleteFile(DBName);

  FDConnection1.Params.Values['database'] := DBName;
  FDConnection1.LoginPrompt := False;
  FDConnection1.DriverName := 'SQLite';
  FDConnection1.Connected:= True;

  FDQuery1.Connection := FDConnection1;
  FDQuery1.SQL.Text :=
    'CREATE TABLE IF NOT EXISTS MyTable ('+
    'ID LARGEINT PRIMARY KEY,'+
    'Name NVARCHAR(80) NOT NULL'+
    ');'; //don't use "WITHOUT ROWID" here
  FDQuery1.ExecSQL;

  FDTable1.Connection := FDConnection1;
  FDTable1.Fields.Clear;
  FDTable1.TableName := 'MyTable';
  FDTable1.Open();
  FDTable1.InsertRecord([1, 'First']);
  FDConnection1.Commit;
end;

相关问题