问题
I am using the latest Zeos with SQLite 3. It is generally going well, converting from MySQL, once we made all the persistent integer field TLargeInt
.
But when we use a column definition unsigned big int
(the only unsigned type allowed according to https://www.sqlite.org/datatype3.html), Delphi is calling the resulting field a ftWidestring
.
回答1:
No, it does not "revert" to string, SQlite just stores the data as it is provided.
As the documentation states:
SQLite supports the concept of "type affinity" on columns. The type affinity of a column is the recommended type for data stored in that column. The important idea here is that the type is recommended, not required. Any column can still store any type of data. It is just that some columns, given the choice, will prefer to use one storage class over another. The preferred storage class for a column is called its "affinity".
If you supplied/bind a text value, it would store a text value. There is no conversion to the type supplied in the CREATE TABLE statement, as it may appear in other more strict RBMS, e.g. MySQL.
So in your case, if you retrieve the data as ftWideString
, I guess this is because you wrote the data as TEXT. For instance, the tool or program creating the SQLite3 content from your MySQL is writing this column as TEXT.
About numbers, there is no "signed"/"unsigned", nor precision check in SQLite3. So if you want to store "unsigned big int" values, just use INTEGER, which are Int64.
But, in all cases, even if SQLite3 API does support UNSIGNED 64 bit integers, this sqlite3_uint64
type may hardly be supported by the Zeos/ZDBC API or by Delphi (older versions of Delphi do NOT support UInt64). To be sure, you should better retrieve such values as TEXT, then convert it as UInt64
manually in your Delphi code.
Update:
Are you using the TDataSet
descendant provided by Zeos? This component is tied to DB.Pas
, so expects a single per-column type. It may be the source of confusion of your code (which you did not show at all, so it is hard to figure out what's happening).
You should better use the lower level ZDBC interface, which allows to retrieve the column type for each row, and call the value getter method as you need.
回答2:
The latest Zeos, that is, which one? See if it's the same in 7.2 svn 3642: http://svn.code.sf.net/p/zeoslib/code-0/branches/testing-7.2/
Michal
回答3:
Zeos uses the following code (in ZDbcSqLiteUtils.pas
) to determine a column's type:
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;
If your table uses any other type name, or if the SELECT output column is not a table column, then Zeos falls back to stString
.
There's nothing you can do about that; you'd have to read the values from the string field (and hope that the conversion to string and back does not lose any information).
It might be a better idea to use some other library that does not assume that every database has fixed column types.
来源:https://stackoverflow.com/questions/32689279/why-is-delphi-zeos-giving-me-widestring-fields-in-sqlite-when-i-ask-for-unsign