我正在使用带有 SQLite 3 的最新 Zeos。一旦我们制作了所有持久整数字段,它通常运行良好,从 MySQL 转换TLargeInt
。
但是当我们使用列定义unsigned big int
(根据https://www.sqlite.org/datatype3.html允许的唯一无符号类型)时,Delphi 调用结果字段 a ftWidestring
。
不,它不会“恢复”为字符串,SQlite 只是存储提供的数据。
正如文档所述:
SQLite 支持列上的“类型关联”概念。列的类型亲和性是存储在该列中的数据的推荐类型。这里的重要思想是该类型是推荐的,而不是必需的。任何列仍然可以存储任何类型的数据。只是某些列,如果可以选择,会更喜欢使用一个存储类而不是另一个。列的首选存储类称为“亲和性”。
如果您提供/绑定一个文本值,它将存储一个文本值。没有转换为 CREATE TABLE 语句中提供的类型,因为它可能出现在其他更严格的 RBMS 中,例如 MySQL。
因此,在您的情况下,如果您将数据检索为ftWideString
,我想这是因为您将数据写为 TEXT。例如,从 MySQL 创建 SQLite3 内容的工具或程序正在将此列写为 TEXT。
关于数字,SQLite3 中没有“有符号”/“无符号”,也没有精度检查。因此,如果您想存储“无符号大整数”值,只需使用 INTEGER,即 Int64。
但是,在所有情况下,即使SQLite3 API 确实支持 UNSIGNED 64 位整数,Zeos/ZDBC API 或 Delphi 可能几乎不支持这种sqlite3_uint64
类型(旧版本的 Delphi 不支持 UInt64)。可以肯定的是,您最好检索 TEXT 等值,然后UInt64
在 Delphi 代码中手动转换它。
更新:
你用的TDataSet
是Zeos提供的后代吗?此组件与 绑定DB.Pas
,因此需要一个每列类型。这可能是您的代码混乱的根源(您根本没有显示,因此很难弄清楚发生了什么)。
您最好使用较低级别的 ZDBC 接口,该接口允许检索每行的列类型,并根据需要调用 value getter 方法。
Zeos 使用以下代码 (in ZDbcSqLiteUtils.pas
) 来确定列的类型:
Result := stString;
...
if StartsWith(TypeName, 'BOOL') then
Result := stBoolean
else if TypeName = 'TINYINT' then
Result := stShort
else if TypeName = 'SMALLINT' then
Result := stShort
else if TypeName = 'MEDIUMINT' then
Result := stInteger
else if TypeName = {$IFDEF UNICODE}RawByteString{$ENDIF}('INTEGER') then
Result := stLong //http://www.sqlite.org/autoinc.html
else if StartsWith(TypeName, {$IFDEF UNICODE}RawByteString{$ENDIF}('INT')) then
Result := stInteger
else if TypeName = 'BIGINT' then
Result := stLong
else if StartsWith(TypeName, 'REAL') then
Result := stDouble
else if StartsWith(TypeName, 'FLOAT') then
Result := stDouble
else if (TypeName = 'NUMERIC') or (TypeName = 'DECIMAL')
or (TypeName = 'NUMBER') then
begin
{ if Decimals = 0 then
Result := stInteger
else} Result := stDouble;
end
else if StartsWith(TypeName, 'DOUB') then
Result := stDouble
else if TypeName = 'MONEY' then
Result := stBigDecimal
else if StartsWith(TypeName, 'CHAR') then
Result := stString
else if TypeName = 'VARCHAR' then
Result := stString
else if TypeName = 'VARBINARY' then
Result := stBytes
else if TypeName = 'BINARY' then
Result := stBytes
else if TypeName = 'DATE' then
Result := stDate
else if TypeName = 'TIME' then
Result := stTime
else if TypeName = 'TIMESTAMP' then
Result := stTimestamp
else if TypeName = 'DATETIME' then
Result := stTimestamp
else if Pos('BLOB', TypeName) > 0 then
Result := stBinaryStream
else if Pos('CLOB', TypeName) > 0 then
Result := stAsciiStream
else if Pos('TEXT', TypeName) > 0 then
Result := stAsciiStream;
如果您的表使用任何其他类型名称,或者如果 SELECT 输出列不是表列,则 Zeos 回退到stString
. 您对此无能为力。您必须从字符串字段中读取值(并希望转换为字符串并返回不会丢失任何信息)。
使用不假定每个数据库都有固定列类型的其他库可能是一个更好的主意。
最新的Zeos,也就是哪一个?查看 7.2 svn 3642 中是否相同:http: //svn.code.sf.net/p/zeoslib/code-0/branches/testing-7.2/
迈克尔