database - 使用 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 资源管理器工具查看数据库,它也无法读取时间值,但我注意到它确实从一些示例数据库中读取了日期时间,所以很清楚能行得通。
谁能告诉我我错过了什么。谢谢
解决方案
尝试在 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
推荐阅读
- ruby-on-rails - Rails API 返回密码不能为 has_secure_password 的空白
- ios - 如何在横向模式下拍摄 MKMapView 快照
- linux - /usr/bin/ld: ../freeglut/libfreeglut_static.a(freeglut_state.o): 未定义对 Box2d 中符号“XGetWindowAttributes”的引用
- java - 可空 Gson 改造字段
- android - 有时在关闭和打开 GPS 后无法获取当前位置
- php - Instamojo 支付集成 - Webhook 问题
- r - 在 R 中向量化两个相似的函数适用于一个
- corda - 与corda的可升级合同
- linkedin - Linkedin 个人资料图片网址拒绝访问
- c# - 如何使用 Moq 和 Xunit 为以下代码编写测试用例?