首页 > 解决方案 > 使用 Delphi 和 FireDAC 从数据库中读取 DateTime

问题描述

我无法使用 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。

如果我生成一个带有链接到数据源和 DBgrid 的 FDConnection1 和 FDQuery1 的 Delphi 程序,它将读取“Fred”而不是时间。FDquery1 asstring 返回的值是 '' 而 asfloat 是 0。如果我尝试使用 FireDAC 资源管理器工具查看数据库,它也无法读取时间值,但我注意到它确实从一些示例数据库中读取了日期时间,所以很清楚能行得通。

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

标签: databasesqlitedelphifiredac

解决方案


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

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

顺便说一句,一般来说,使用参数化的 INSERT 语句比使用像上面这样的文字语句更好,但在这里并不实际,因为您插入的now是 Sqlite 返回的值而不是 Delphinow 函数。

**更新:** 下面的代码来自一个最小的项目,它创建您的示例表,在其中插入一行,然后将其呈现在 db-aware 控件(DBGrid、DBEdit)中进行编辑。这一切都完全按照它应该的方式工作。特别是,通过这些控件对行数据所做的任何更改都会在下次运行应用程序时保留。请注意,创建表的 SQL 在 Name 列/字段上指定了一个主键:这是 FDQuery1 生成将更改保存回磁盘表所需的 UPDATE 语句所必需的。

处理程序中的代码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

推荐阅读