2010-05-28 4 views
21

У меня есть база данных Sqlite, в которой я хочу выбрать строки, значение которых в столбце TIMESTAMP до определенной даты. Я бы подумал, что это просто, но я не могу это сделать. Я попытался это:Как сравнить значения sqlite TIMESTAMP

SELECT * FROM logged_event WHERE logged_event.CREATED_AT < '2010-05-28 16:20:55'

и различные вариации на ней, как с функциями даты. Я читал http://sqlite.org/lang_datefunc.html и http://www.sqlite.org/datatypes.html, и я ожидал бы, что столбец будет иметь числовой тип и что сравнение будет выполнено по значению timestamp unix. Совершенно очевидно. Кто может помочь? Если это имеет значение, я пробую это в Sqlite Expert Personal.

Edit:

Вот тип Описание таблицы:

CREATE TABLE [logged_event] 
(
[id] INTEGER NOT NULL PRIMARY KEY, 
[created_at] TIMESTAMP, 
[name] VARCHAR(64), 
[data] VARCHAR(512) 
); 

И данные испытаний:

INSERT INTO table VALUES(1,'2010-05-28T15:36:56+0200','test','test'); 
INSERT INTO table VALUES(2,'2010-05-28T16:20:49+0200','test','test'); 
INSERT INTO table VALUES(3,'2010-05-28T16:20:51+0200','test','test'); 
INSERT INTO table VALUES(4,'2010-05-28T16:20:52+0200','test','test'); 
INSERT INTO table VALUES(5,'2010-05-28T16:20:53+0200','test','test'); 
INSERT INTO table VALUES(6,'2010-05-28T16:20:55+0200','test','test'); 
INSERT INTO table VALUES(7,'2010-05-28T16:20:57+0200','test','test'); 
+0

Какую версию SQLite вы используете? Документация 3.x.x не определяет, какой столбец с именем TIMESTAMP отличен по типу. http://sqlite.org/datatype3.html –

+1

Sqlite 3. Поскольку все, что не ограничено набором текстовых типов (TEXT, BLOB, несколько других), является числовым, согласно документации, я предположил, что TIMESTAMP будет числовой тип. Следует отметить, что я создаю эту таблицу с помощью инструмента Propel ORM, и это автоматически сгенерированная таблица, поэтому я не могу легко переключиться на другой тип. Я думаю, если бы я мог заставить этот столбец вести себя как DATETIME, я был бы на полпути. – Roel

ответ

36

Проблема заключается в том, как вы вставили данные в таблицу: синтаксис +0200 не соответствует ни одному из SQLite's time formats:

  1. YYYY-MM-DD
  2. YYYY-MM-DD HH : ММ
  3. ГГГГ-ММ-ДД ЧЧ: ММ: СС
  4. ГГГГ-ММ-ДД ЧЧ: ММ: СС.ссс
  5. YYYY-MM-ДДTчч: ММ
  6. YYYY-MM-ДДTчч: ММ : СС
  7. YYYY-MM-ДДTчч: ММ: СС.ссс
  8. HH: MM
  9. HH: MM: SS
  10. HH: MM: СС.ссс
  11. Теперь
  12. DDDDDDDDDD

Изменение его использовать формат СС.ссс работает правильно:

sqlite> CREATE TABLE Foo (created_at TIMESTAMP); 
sqlite> INSERT INTO Foo VALUES('2010-05-28T15:36:56+0200'); 
sqlite> SELECT * FROM Foo WHERE foo.created_at < '2010-05-28 16:20:55'; 
sqlite> SELECT * FROM Foo WHERE DATETIME(foo.created_at) < '2010-05-28 16:20:55'; 
sqlite> INSERT INTO Foo VALUES('2010-05-28T15:36:56.200'); 
sqlite> SELECT * FROM Foo WHERE DATETIME(foo.created_at) < '2010-05-28 16:20:55'; 
2010-05-28T15:36:56.200 

Если вы абсолютно не можете изменить формат, когда он вставлен, вам, возможно, придется вернуться к выполнению «умного» и модификации фактической строки (т. заменить + на . и т. д.).


(оригинальный ответ)

Вы не описали, какой тип данных содержится в вашем CREATED_AT колонке.Если это действительно DateTime, он корректно сравниваться строкой:

sqlite> SELECT DATETIME('now'); 
2010-05-28 16:33:10 
sqlite> SELECT DATETIME('now') < '2011-01-01 00:00:00'; 
1 

Если он хранится в виде метки времени UNIX, вам нужно вызвать DATETIME функции со вторым аргументом в качестве 'unixepoch' для сравнения строки:

sqlite> SELECT DATETIME(0, 'unixepoch'); 
1970-01-01 00:00:00 
sqlite> SELECT DATETIME(0, 'unixepoch') < '2010-01-01 00:00:00'; 
1 
sqlite> SELECT DATETIME(0, 'unixepoch') == DATETIME('1970-01-01 00:00:00'); 
1 

Если ни один из тех, кто решить вашу проблему (и даже если они делают!), вы должны всегда разместить некоторые данные так, чтобы другие люди могли воспроизвести вашу проблему. Вы даже можете придумать подмножество ваших исходных данных, которые все еще воспроизводят проблему.

+0

Да, я тоже видел эти примеры в руководстве. То, что я хочу сделать, - SELECT * из таблицы WHERE column <'2010-05-23 14:32:29'; и я предполагаю, что мне нужно добавить функцию там где-то в той или иной форме, но я понятия не имею, как это сделать. – Roel

+1

Спасибо, действительно, спецификатор часовой пояс сделал это. Это усугублялось тем, что Sqlite Expert не показывал эту часть - она ​​появилась только тогда, когда я выполнил командную строку SELECT для размещения здесь тестовых данных. Вырубили решение в моей программе, чтобы оставить часть часового пояса. – Roel

1

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

Вы можете определить свои собственные хранимые функции для выполнения сравнений с помощью SQLite create_function() API.

+0

Обратите внимание, что проблема, связанная с тем, что я использовал _adding_ периоды времени, хотя и не сравнивая. Я думаю, что ответ Марка, вероятно, лучше в этой ситуации. –

0

Насколько я могу судить, вполне разумно включить спецификатор часового пояса; см. текст «Форматы от 2 до 10 могут ...» на http://www.sqlite.org/lang_datefunc.html Однако проблема заключается в том, что только даты используют интерпретацию временных меток в качестве дат. Поэтому для фактического сравнения вам нужно либо передать временную метку с помощью функции даты, либо хранить вещи, такие как сравнение строк. Один из подходов заключался бы в кодировании вашего приложения, так что вы вызывали datetime на каждое значение, которое вы вставляете, и на каждое значение буква в выражении select. Тем не менее, просто отсутствие часового пояса, как предлагается в существующем ответе, может быть проще во многих приложениях.

Смежные вопросы