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