Delphi 7 + Zeos: как предотвратить преобразование sqlite 3 даты и целого числа/числа с плавающей запятой в строку?

Тестовая база данных:

create table a ( d date not null primary key);
create table b ( d date not null primary key);
insert into a values ('2013-01-01');
insert into b values ('2014-01-01');

Используя Zeos lib с Delphi 7, все эти запросы возвращают TDateTimeField:

select d from a order by 1;

select d from b order by 1;

select d from a union all select d from b;

select * from (select d from a union all select d from b) s;

Однако этот запрос возвращает TStringField:

select * from (select d from a union all select d from b) s order by 1;

Вопросы:

  • Почему это?
  • Как предотвратить это?
  • Это ошибка? Как, черт возьми, заказ результирующего набора меняет тип столбца????
  • Это серьезная проблема, потому что я не могу генерировать SQL-запросы из своей программы и открывать их в TZReadOnlyQuery, созданном во время разработки.

Обновление: оно также не работает с целыми числами.

create table c ( id integer not null primary key);
create table d ( id integer not null primary key);
insert into c values(1);
insert into d values(2);

Это приводит к TLargeIntField:

select * from c order by 1

select * from d order by 1

select * from ( select * from c union all select * from d) s

Однако это приводит к TStringField:

select * from ( select * from c union all select * from d) s order by 1

person nagylzs    schedule 27.03.2014    source источник
comment
Проблема явно с объединением всех. С простым союзом все работает правильно!   -  person nagylzs    schedule 28.03.2014
comment
То же самое с РЕАЛЬНЫМИ полями. Я только что проверил. Если я добавлю заказ к тому времени, он изменится с TFloatField на TStringField. Очень жаль.   -  person nagylzs    schedule 28.03.2014
comment
Я только что проверил это с Zeos 7.1.3-stable, и он создает TDateField и TLargeintField, как и ожидалось (хотя в Delphi XE)   -  person Stefan Glienke    schedule 28.03.2014


Ответы (1)


Как указано здесь: http://www.sqlite.org/datatype3.html

В SQLite нет класса хранения, предназначенного для хранения дат и/или времени. Вместо этого встроенные функции даты и времени SQLite способны хранить даты и время в виде значений TEXT, REAL или INTEGER:

ТЕКСТ в виде строк ISO8601 ("ГГГГ-ММ-ДД ЧЧ:ММ:СС.ССС").
REAL как число дней по юлианскому календарю, количество дней, прошедших с полудня по Гринвичу 24 ноября 4714 г. до н.э. по пролептическому григорианскому календарю.
INTEGER as Unix Time, количество секунд с 01-01-1970 00:00:00 UTC. Приложения могут хранить дату и время в любом из этих форматов и свободно конвертировать между форматами, используя встроенные функции даты и времени.

Итак, вы можете попробовать приведенное ниже утверждение и опубликовать результаты?!

select date(*) as test from (select date(d) from a union all select date(d) from b) s order by 1;
person Filipe YaBa Polido    schedule 27.03.2014
comment
Я знаю, что SQLite хранит внутри себя только эти три типа. Однако этот тип автоматически преобразуется базовой библиотекой zeos! Мой вопрос был задан конкретно о Delphi 7 + Zeos lib + SQLite. Итак, если ZeosLib может преобразовывать строки даты в поле TDateField для выбора объединения, то почему она не может сделать то же самое для выбора объединения всех? Есть ли способ написать запрос, который делает то, что я хочу? Конечно не хотелось бы переписывать zeoslib. - person nagylzs; 28.03.2014
comment
Верно. Какую версию Zeos вы используете? - person Filipe YaBa Polido; 28.03.2014
comment
Я понятия не имею. Этот проект был создан с помощью Delphi 7 несколько лет назад. Примерно в 2004 году. Я бы с удовольствием обновился до более новой версии, но боюсь, что это сломает весь остальной код. Это должно быть что-то фундаментальное в союзе и порядке. Я только что обнаружил, что эта проблема также относится к действительным числам! Они преобразуются в TFloatField, если я не комбинирую объединение с порядком. Затем они становятся струнами. :-( - person nagylzs; 28.03.2014
comment
хорошо, пожалуйста, сделайте этот тест выше и сообщите мне результаты. Я устанавливаю Zeos, чтобы попробовать. - person Filipe YaBa Polido; 28.03.2014
comment
Я только что установил последнюю версию ZeosLib на Delphi 7, и мой код не сломался. К счастью, ваш запрос открывается как поле даты. Но вот следующая проблема: он по-прежнему не работает с целыми числами. (будет редактировать вопрос) - person nagylzs; 28.03.2014
comment
Вот временное решение — буквально временное: удалить таблицу, если она существует _tmp; создайте таблицу _tmp as select ...... ‹мой союз, все выберите здесь›; выберите * из _tmp порядка по любому_столбцу; Последний выбор используется в TZReadOnlyQuery, и все типы столбцов в порядке. Так что если у кого такая проблема. Я не удовлетворен этим решением, но, по крайней мере, оно работает! - person nagylzs; 28.03.2014
comment
Ну, не совсем потому, что varchar(30) преобразуется в text-›Memo, но на данный момент это лучший вариант. - person nagylzs; 28.03.2014