我刚刚了解到Firefox的Sqlite Manager插件将在11月消失,所以我一直在尝试在Delphi中重新创建它的功能:打开Sqlite数据库,输入SQL查询。我正在运行东京。
我的问题是Sqlite字段定义为'date'。虽然Sqlite允许指定数据类型,但它允许在任何字段中放置任何东西。 FireDAC处理整数或浮点字段中的错误条目('bar'变为0,'32foo'变为32),但它在描述为'date'的字段上打嗝。
例如,我有一张桌子:
CREATE TABLE "someTable" ("id" INTEGER, "s" text(10), "d" date)
有了这些数据:
INSERT INTO "someTable" VALUES ("1","good date","2017-09-09");
INSERT INTO "someTable" VALUES ("2","bad date","2017-09-0b");
INSERT INTO "someTable" VALUES ("3","empty d","");
INSERT INTO "someTable" VALUES ("4","null date",null);
使用SQL =“select * from someTable”打开FDQuery q1,错误的日期(例如第二条记录)会引发EConvertError(“日期编码的无效参数”)。我试图通过添加maprule来解决它(q1是FDQuery):
with q1.FormatOptions do begin
OwnMapRules := True;
with MapRules.Add do begin
SourceDataType := dtDate;
TargetDataType := dtAnsiString;
sizemin := 10;
sizemax := 256;
PrecMin := -1;
PrecMax := -1;
ScaleMin := -1;
ScaleMax := -1;
end;
end;
然而,这会引发EFDException:
[FireDAC] [DATS] -32。可变长度列溢出。值长度 - [10],列最大长度 - [0]。
我错过了什么?
答案 0 :(得分:1)
问题是FireDAC期望 DATE 数据类型值表示为固定格式的字符串 YYYY-MM-DD ,其中所有成员必须是整数。内部使用的 FDStr2Int 函数不使用任何无效输入的检测,并且直接使用由 0 char移位的ASCII普通值,因此输入如:解析后, GHIJ-KL-MN 导致年份 25676 ,月份 298 , 320 。然后只是将这些误解的值传递给EncodeDate函数,对于这些值失败,除了你提到的例外:
日期编码的参数无效
以上内容发生在GetData方法( ParseDate 嵌套函数)中。在FireDAC方面解决此问题的一种可能方法是使用更安全的函数TryEncodeDate而不是直接编码尝试。类似的问题是 TIME 数据类型字符串值。