使用 Delphi 和 FireDAC 从数据库中读取日期时间

Reading DateTime from Database using Delphi and FireDAC

我无法使用 Delphi 10.3 和 FireDAC 从 SQLite 数据库中读取日期时间。 作为最简单的示例,我使用 sqlite 创建一个示例数据库,如下所示:

.open Test.db
CREATE TABLE "TABLE1" ("Name"VarChar(16), "Time" datetime); 
INSERT INTO Table1 (Name,Time) VALUES("Fred",time('now'));

然后

select * from Table1

按照预期给出 Fred|16:52:57。

如果我生成一个 Delphi 程序,其中包含链接到数据源和 DBgrid 的 FDConnection1 和 FDQuery1,它将读取 "Fred" 而不是时间。 FDquery1 asstring返回的值为'',asfloat为0。 如果我尝试使用 FireDAC 资源管理器工具查看数据库,它也无法读取时间值,但我注意到它确实从一些示例数据库中读取了日期时间,因此它显然可以工作。

谁能告诉我我错过了什么。 谢谢

尝试在 Delphi 代码中将 SQL 语句构造为字符串可能有点容易出错。但是,你应该会发现下面的代码可以正确执行

procedure TForm2.btnInsertRowClick(Sender: TObject);
const
  sInsertRow = ' INSERT INTO Table1 (Name,time) VALUES(''Fred'',datetime(''now''))';
begin
  FDConnection1.ExecSql(sInsertRow);
end;

顺便说一句,一般来说,使用参数化的 INSERT 语句比使用上面的文字语句更好,但它在这里并不实用,因为你插入的是 Sqlite 返回的 now 值而不是Delphi now 功能。

**更新:**下面的代码来自创建示例的最小项目table, 向其中插入一行,然后将其呈现在可识别数据库的控件(DBGrid、DBEdit)中进行编辑。 这一切都完全按照它应该的方式工作。特别是,通过 当下一个应用程序 运行 时,这些控件将被保留。请注意,创建 table 的 SQL 在名称 column/field 上指定了一个主键:这是 FDQuery1 生成将更改保存回磁盘所需的 UPDATE 语句所必需的table.

btnSelectClick 处理程序中的代码展示了如何设置 time 字段的 DisplayFormat 和 EditMask 属性,以便它只显示存储的 DateTime 数据的时间部分。

type
  TForm2 = class(TForm)
    FDConnection1: TFDConnection;
    FDQuery1: TFDQuery;
    DBGrid1: TDBGrid;
    DBNavigator1: TDBNavigator;
    DataSource1: TDataSource;
    DBEdit1: TDBEdit;
    btnCreateTable: TButton;
    btnInsertRow: TButton;
    btnSelect: TButton;
  [...]
  public

[...]

const
  sCreateTable = 'CREATE TABLE ''TABLE1'' (''Name'' VarChar(16) primary key, ''Time'' datetime)';
  sInsertRow = ' INSERT INTO Table1 (Name,time) VALUES(''Fred'',datetime(''now''))';
  sSelect = 'select * from table1';

procedure TForm2.btnCreateTableClick(Sender: TObject);
begin
  FDConnection1.Connected := True;
  FDConnection1.ExecSql(sCreateTable);
end;

procedure TForm2.btnInsertRowClick(Sender: TObject);
const
begin
  FDConnection1.ExecSql(sInsertRow);
end;

procedure TForm2.btnSelectClick(Sender: TObject);
var
  AField : TDateTimeField;
begin
  FDQuery1.SQL.Text := sSelect;
  FDQuery1.Open;

  //   The following shows how to  control how the time field is formatted for display
  //   in gui controls using the field's DisplayFormat
  //   and how to set up its EditMask for editing
  AField := FDQuery1.FieldByName('time') as TDateTimeField;
  AField.DisplayFormat := 'hh:nn:ss';
  AField.EditMask := '!90:00:00;1;_';
end;
end.

.DFM 文件

object Form2: TForm2
[...]
  object FDConnection1: TFDConnection
    Params.Strings = (
      'Database=D:\Delphi\Code\FireDAC\db1.sqlite'
      'DriverID=SQLite')
    LoginPrompt = False
  end
  object FDQuery1: TFDQuery
    Connection = FDConnection1
  end
  object DataSource1: TDataSource
    DataSet = FDQuery1
  end
  object DBGrid1: TDBGrid
    DataSource = DataSource1
  end
  object DBNavigator1: TDBNavigator
    DataSource = DataSource1
  end
  object DBEdit1: TDBEdit
    DataField = 'Time'
    DataSource = DataSource1
  end
end