Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / SQLite Новый топик    Ответить
 прочитать значение поле INTEGER как float  [new]
Belotsky Serge
Member

Откуда: Гомель
Сообщений: 241
Добрый день!

Нужно прочитать вещественное значение поля объявленное как INTEGER в одной таблице БД.
И у меня что-то не выходит (читается только как целое).
Для проверки сделал свой код.

Для работы с SQLite используется TSQLConnection (dbExpress).

               
var
 dsData :TDataSet;
 fV :double;
 ...
 Params.CreateParam(TFieldType.ftInteger,'Field1',ptInput);
 Params.ParamByName('Field1').AsFloat := 11.3;  // запись выполняется корректно, как 11.3
 ...
 SQLConnection1.Execute(cInsertQuery,Params); // вставить запись с параметрами
...
// чтение вставленной записи
 fV := dsData.FieldByName('Field1').AsFloat; // fV = 11 (целое)


При этом SQLite Expert показывает корректное вещественное значение (см. скриншот), но выполняет нестандартное фоновое выделение.

Пробовал разные AsXXX (AsString, AsVariant, AsSingle) - всегда возвращается целое значение.

БД не моя, мне нужно прочитать корректное вещественное значение. Как это можно сделать?

К сообщению приложен файл. Размер - 6Kb
24 апр 19, 16:45    [21870780]     Ответить | Цитировать Сообщить модератору
 Re: прочитать значение поле INTEGER как float  [new]
pit_alex
Member

Откуда: Kharkov
Сообщений: 683
Belotsky Serge,

какой DBExpress драйвер для SQLite используете, DDL таблицы?

Params.CreateParam(TFieldType.ftInteger,'Field1',ptInput);

TFieldType.ftInteger???
25 апр 19, 07:06    [21871133]     Ответить | Цитировать Сообщить модератору
 Re: прочитать значение поле INTEGER как float  [new]
Belotsky Serge
Member

Откуда: Гомель
Сообщений: 241
pit_alex
Belotsky Serge,

какой DBExpress драйвер для SQLite используете, DDL таблицы?

Params.CreateParam(TFieldType.ftInteger,'Field1',ptInput);

TFieldType.ftInteger???


Честно говоря, не знаю где она берет этот драйвер (Delphi XE3). Делал я на примерах этого ресурса:
https://www.webdelphi.ru/2012/10/sqlite-v-delphi-xe3/
https://www.webdelphi.ru/2013/01/sqlite-v-delphi-xe3-2/

Настраиваю я соединение примерно так:
+
object SQLConnection1: TSQLConnection
    ConnectionName = 'SQLITECONNECTION'
    DriverName = 'Sqlite'
    LoginPrompt = False
    Params.Strings = (
      'DriverName=Sqlite'
      'Database='
      'UserName=SYSDBA'
      'Password=masterkey'
      'TableName=')
    Left = 400
    Top = 80
  end



Поле объявлено вот так:
CREATE TABLE tbMain(..., Field1 INTEGER ...);


Да, я обратил внимание, что параметр объявлен как TFieldType.ftInteger. Но опять же, мне нужно было полностью сымитировать занесение данных как оригинальной таблице БД. (БД не моя).

Я проделал это с ftFloat, данные записались в таблицу точно также.
25 апр 19, 07:59    [21871163]     Ответить | Цитировать Сообщить модератору
 Re: прочитать значение поле INTEGER как float  [new]
pit_alex
Member

Откуда: Kharkov
Сообщений: 683
Belotsky Serge,

Тип поля какой?
25 апр 19, 08:32    [21871178]     Ответить | Цитировать Сообщить модератору
 Re: прочитать значение поле INTEGER как float  [new]
Belotsky Serge
Member

Откуда: Гомель
Сообщений: 241
pit_alex
Belotsky Serge,

Тип поля какой?


Не понимаю вопрос, вроде INTEGER. См. скриншот.
В поле типа INTEGER занесено значение 11.3. Вопрос: как его прочитать как '11.3', а не как '11'.

К сообщению приложен файл. Размер - 36Kb
25 апр 19, 08:52    [21871193]     Ответить | Цитировать Сообщить модератору
 Re: прочитать значение поле INTEGER как float  [new]
Dima T
Member

Откуда:
Сообщений: 13672
ИМХО вопрос не по SQLite, а по Дельфи, из которого чтение идет. Советую спросить в форуме по Делфи
25 апр 19, 09:16    [21871208]     Ответить | Цитировать Сообщить модератору
 Re: прочитать значение поле INTEGER как float  [new]
Belotsky Serge
Member

Откуда: Гомель
Сообщений: 241
Удалось прочитать при помощи вот этого wrapper (Plashenkov):
https://github.com/plashenkov/SQLite3-Delphi-FPC

+
procedure TForm1.FormShow(Sender: TObject);
var
 DB: TSQLite3Database;
 Stmt: TSQLite3Statement;
 DoCreate :boolean;
 fV :double;
 iV :integer;
 S :string;
// IdRec :integer;
begin
 DB := TSQLite3Database.Create;
 try
  DoCreate := not FileExists(ExtractFilePath(Application.ExeName)+'test_int.db');

  DB.Open('test_int.db');

  if DoCreate then
   begin
    DB.Execute('CREATE TABLE test_int (intField INTEGER)');
    // Fill the table with the value
    Stmt := DB.Prepare('INSERT INTO test_int (intField) VALUES (?)');
    try
     Stmt.BindDouble(1, 11.3);
     Stmt.StepAndReset;
//    IdRec := DB.LastInsertRowID;
    finally
     Stmt.Free;
    end;
   end;

  Stmt := DB.Prepare('SELECT intField FROM test_int');
  try
   if(Stmt.Step = SQLITE_ROW)then
    begin
     iV := Stmt.ColumnCount;         // iV = 1
     fV := Stmt.ColumnDouble(0);     // fV = 11.3
     iV := Stmt.ColumnInt(0);        // iV = 11
     S := Stmt.ColumnText(0);        // S = '11.3'
     Label1.Caption := FloatToStr(fV);
    end;
  finally
   Stmt.Free;
  end;
 finally
  FreeAndNil(DB);
 end;
end;

Данный враппер базируется на sqlite3.dll.
Вопрос: а при помощи чистого dbExpress (без подключения dll) - это можно сделать?

К сообщению приложен файл. Размер - 8Kb
25 апр 19, 09:27    [21871217]     Ответить | Цитировать Сообщить модератору
 Re: прочитать значение поле INTEGER как float  [new]
Belotsky Serge
Member

Откуда: Гомель
Сообщений: 241
Belotsky Serge,

PS: Дальнейшие эксперименты, показали, что через dbExpress также нормально читаются вещественные значения из полей типа INTEGER, но только для таблиц, которые я сам создал и заполнил. Оригинальные же таблицы корректно можно прочитать только через враппер (т.е. через sqlite3.dll). Через dbExpress почему-то упорно возвращаются целочисленные значения.

В чем разница между этими БД понять не могу, для меня они практически одинаковые.
25 апр 19, 10:46    [21871307]     Ответить | Цитировать Сообщить модератору
 Re: прочитать значение поле INTEGER как float  [new]
pit_alex
Member

Откуда: Kharkov
Сообщений: 683
Belotsky Serge,

в sqlite можно создавать колонки с ЛЮБЫМИ типами данных, т.е.

CREATE TABLE TEST(FIELD1 MY_NAME ..


и вставлять любые значения в любые поля, в Delphi не может быть разных типов данных для разных записей в одном поле.

SLite3.dll это движок самого SQLite и стандартный dbExpress драйвер то же работает через эту либу.

Либо создавайте поле FLOAT и будет вам счастье
25 апр 19, 10:58    [21871329]     Ответить | Цитировать Сообщить модератору
 Re: прочитать значение поле INTEGER как float  [new]
Belotsky Serge
Member

Откуда: Гомель
Сообщений: 241
pit_alex
Belotsky Serge,

SLite3.dll это движок самого SQLite и стандартный dbExpress драйвер то же работает через эту либу. ???

Либо создавайте поле FLOAT и будет вам счастье


Еще раз: оригинальная БД - чужая, я не могу задать FLOAT! Она ко мне поступает готовая. Я только хочу ее прочитать корректно. Если я сделаю аналог этой БД и/или таблицы таблицы (неважно как: через dbExpress или через SQLite3.dll), то у меня корректно получается ее прочитать (любым способом: через dbExpress или SQLite3.dll). А вот прочитать оригинальную БД корректно у меня получается только через SQLite.dll, dbExpress здесь почему-то не работает :(
25 апр 19, 11:10    [21871346]     Ответить | Цитировать Сообщить модератору
 Re: прочитать значение поле INTEGER как float  [new]
Leonid Kudryavtsev
Member

Откуда:
Сообщений: 7659
Belotsky Serge
В поле типа INTEGER занесено значение 11.3. Вопрос: как его прочитать как '11.3', а не как '11'.

Может я сильно тупой, но КАК в поле integer может быть значение 11.3 ?
25 апр 19, 16:39    [21871865]     Ответить | Цитировать Сообщить модератору
 Re: прочитать значение поле INTEGER как float  [new]
Dima T
Member

Откуда:
Сообщений: 13672
Leonid Kudryavtsev
Belotsky Serge
В поле типа INTEGER занесено значение 11.3. Вопрос: как его прочитать как '11.3', а не как '11'.

Может я сильно тупой, но КАК в поле integer может быть значение 11.3 ?

В SQLite нетипизированные поля.
https://www.sqlite.org/datatype3.html
SQLite uses a more general dynamic type system. In SQLite, the datatype of a value is associated with the value itself, not with its container. The dynamic type system of SQLite is backwards compatible with the more common static type systems of other database engines in the sense that SQL statements that work on statically typed databases should work the same way in SQLite. However, the dynamic typing in SQLite allows it to do things which are not possible in traditional rigidly typed databases.
25 апр 19, 16:45    [21871872]     Ответить | Цитировать Сообщить модератору
 Re: прочитать значение поле INTEGER как float  [new]
Leonid Kudryavtsev
Member

Откуда:
Сообщений: 7659
IMHO
Подозреваю, тогда так же, как и в других СУБД. Привести в SELECT поле к нужному/правильному типу (float) и не изврашаться. Беглый поиск по доке говорит, что конструкция CAST в SQLLite присутствует.

https://www.sqlite.org/lang_expr.html

Не проверял.
25 апр 19, 17:00    [21871890]     Ответить | Цитировать Сообщить модератору
 Re: прочитать значение поле INTEGER как float  [new]
Belotsky Serge
Member

Откуда: Гомель
Сообщений: 241
Leonid Kudryavtsev
Belotsky Serge
В поле типа INTEGER занесено значение 11.3. Вопрос: как его прочитать как '11.3', а не как '11'.

Может я сильно тупой, но КАК в поле integer может быть значение 11.3 ?


Вот HEX представление значения этого поля. Можете проверить, это double = 11.3.

К сообщению приложен файл. Размер - 70Kb
25 апр 19, 17:20    [21871910]     Ответить | Цитировать Сообщить модератору
 Re: прочитать значение поле INTEGER как float  [new]
Leonid Kudryavtsev
Member

Откуда:
Сообщений: 7659
IMHO Если сделать CAST в float (в SELECT), то думаю Delphi должен нормально прочитать.
25 апр 19, 17:24    [21871914]     Ответить | Цитировать Сообщить модератору
 Re: прочитать значение поле INTEGER как float  [new]
Belotsky Serge
Member

Откуда: Гомель
Сообщений: 241
Leonid Kudryavtsev
IMHO
Подозреваю, тогда так же, как и в других СУБД. Привести в SELECT поле к нужному/правильному типу (float) и не изврашаться. Беглый поиск по доке говорит, что конструкция CAST в SQLLite присутствует.

https://www.sqlite.org/lang_expr.html

Не проверял.


Да, так можно получить корректное значение. Завтра еще раз перепроверю.
+
    Execute('SELECT CAST(intField as FLOAT) FROM test_int', nil, dsData); // DataK

    while not dsData.Eof do
     begin
//      fV := dsData.FieldByName(dsData.FieldDefs[0].Name).AsFloat; // Ошибка 'Cannot access field 'Column0' as Float
      V := dsData.FieldByName(dsData.FieldDefs[0].Name).Value; // так работает
      S := VarToStr(V);
      ListBox1.Items.Add(Format('%s',[S]));

      dsData.Next;
     end;
25 апр 19, 17:45    [21871928]     Ответить | Цитировать Сообщить модератору
Все форумы / SQLite Ответить