首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当我请求无符号的大整数时,为什么Delphi (Zeos)在SQLite中给我宽字符串字段?

当我请求无符号的大整数时,为什么Delphi (Zeos)在SQLite中给我宽字符串字段?
EN

Stack Overflow用户
提问于 2015-09-21 15:10:24
回答 3查看 1.3K关注 0票数 0

我使用的是最新的Zeos和SQLite 3。当我们把所有的持久整型字段都设为TLargeInt时,从MySQL转换过来的效果一般都很好。

但是,当我们使用列定义unsigned big int (根据https://www.sqlite.org/datatype3.html,这是唯一允许的无符号类型)时,Delphi将结果字段称为ftWidestring

EN

回答 3

Stack Overflow用户

发布于 2015-09-21 15:47:34

不,它不会“还原”为字符串,SQlite只是按提供的方式存储数据。

作为the documentation states

SQLite支持列上的“类型关联”概念。列的类型关联是存储在该列中的数据的推荐类型。这里的重要思想是该类型是推荐的,而不是必需的。任何列仍然可以存储任何类型的数据。只是有些列,如果可以选择,会更喜欢使用一个存储类而不是另一个。列的首选存储类称为它的“亲和性”。

如果您提供/绑定一个文本值,它将存储一个文本值。没有转换到CREATE TABLE语句中提供的类型,因为它可能出现在其他更严格的RBMS中,例如MySQL。

因此,在您的示例中,如果以ftWideString形式检索数据,我猜这是因为您将数据作为文本写入。例如,从MySQL创建SQLite3内容的工具或程序将此列写为文本。

关于数字,在SQLite3中没有“有符号”/“无符号”,也没有精度检查。因此,如果你想存储“无符号大整型”值,只需使用整数,它是Int64。

但是,在所有情况下,即使是SQLite3 API does support UNSIGNED 64 bit integers,Zeos/ZDBC或Delphi也很难支持这种sqlite3_uint64类型(旧版本的Delphi不支持UInt64)。为了确保这一点,您最好将这些值作为文本检索,然后在您的Delphi代码中手动将其转换为UInt64

更新:

您使用的是Zeos提供的TDataSet后代吗?此组件绑定到DB.Pas,因此需要单个每列类型。这可能是代码混乱的根源(您根本没有显示出来,所以很难弄清楚到底发生了什么)。

最好使用较低级别的ZDBC接口,该接口允许检索每行的列类型,并根据需要调用value getter方法。

票数 6
EN

Stack Overflow用户

发布于 2015-09-28 16:06:49

Zeos使用以下代码(在ZDbcSqLiteUtils.pas中)来确定列的类型:

代码语言:javascript
复制
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;

如果您的表使用任何其他类型名称,或者如果选择输出列不是表列,那么Zeos将回退到stString。对此您无能为力;您必须从string字段中读取值(并希望在与string之间的转换过程中不会丢失任何信息)。

使用其他库可能是一个更好的想法,该库不假定每个数据库都有固定的列类型。

票数 1
EN

Stack Overflow用户

发布于 2015-09-21 23:42:18

最新的Zeos,也就是哪一个?看看它在7.2SVN3642中是否相同:http://svn.code.sf.net/p/zeoslib/code-0/branches/testing-7.2/

米哈尔

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32689279

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档