Почему модуль Python Sqlite3 правильно анализирует первый экземпляр этой подстановки параметров, а затем нет? Кэширование?
У меня есть таблица Sqlite3, которая имеет LastUpdated
столбец, содержащий дату и время UTC, отформатированный как "2013-12-24 07:11:21"
и все строки в этой таблице были обновлены 2 дня назад.
Я хочу написать SELECT
оператор для возврата только тех строк, которые не были обновлены в течение некоторого времени:
SELECT LastUpdated FROM UserToken WHERE DATETIME(LastUpdated) < DATETIME('now', '-4 days');
Я пытаюсь выполнить этот запрос из Python, используя стандартную библиотеку sqlite3, и хочу, чтобы устаревший период был переменным. В целях безопасности я попытался использовать подстановку параметров, упомянутую в стандартной документации lib для sqlite3, чтобы использовать переменную stale_delta_parameter
:
dbcursor.execute("SELECT LastUpdated FROM UserToken WHERE TokenValid = 1 AND DATETIME(LastUpdated) < DATETIME('now', ?)", (stale_delta_parameter,))
Первый раз, когда я его запустил, я установил stale_delta_parameter = '-4 days'
и он правильно вернул ноль строк. Затем я изменил значение stale_delta_parameter
на "-1 дней" и запустил запрос. Вместо ожидаемого результата всех строк запрос продолжал возвращать 0 строк.
Когда я перезагружаю компьютер, кажется, что запрос работает нормально с первого раза, но, опять же, если я запускаю скрипт python с одним дельта-значением, как только я изменяю дельта-значение, результаты продолжают оставаться значениями из первого экземпляра. выполнения запроса. Кроме того, если я напишу два оператора SELECT, где query1 установлен в '-4 days'
который не должен возвращать строки и query2 в '-1 days'
который должен вернуть все строки, а затем, после запуска сценария, я переключаю значения в этих запросах, выходные данные запросов не переключаются.
Я подумал, что это могут быть неправильные запросы SQL, поэтому я попытался жестко запрограммировать дельту и запустить запрос в оболочке Sqlite3. Работает так, как я ожидаю каждый раз, поэтому запрос не ошибается.
Затем я попытался расширить переменную stale_delta_parameter
от '-n days'
в DATETIME('now', '-n days')
на всякий случай подстановка параметров не работала правильно внутри специального Sqlite DATETIME()
функция. Странное поведение не изменилось.
Существует ли какое-либо кэширование в стандартной библиотеке Sqlite3 или в DB-API Python, которое может помешать обновлению запроса, передаваемого в базовую базу данных?
В документах я ничего не могу найти, но это единственная теория, которую я могу придумать, которая, кажется, соответствует этому поведению.
Я попытался найти способ напечатать собранный запрос, который передается в БД из Python, поэтому я могу убедиться, что БД не получает обновленную версию запроса, но я не могу найти какой-либо метод для печати собранный запрос от dbcursor.execute(...)
,
Вот фактический код:
til_user_tokens_go_stale = '4 days'
stale_delta_parameter = "DATETIME('now','-%s')" % til_user_tokens_go_stale
dbcursor.execute('''
SELECT UserToken, UserID, AppID
FROM UserToken
WHERE TokenValid = 1 AND DATETIME(LastUpdated) < ?
''', (stale_delta_parameter,))
all_tokens = dbcursor.fetchall()
print len(all_tokens) # For debugging, shows me how many rows are returned
1 ответ
Из документации по SQLite:
Токен "variable" или "parameter" указывает местозаполнитель в выражении для значения, которое заполняется во время выполнения с использованием семейства интерфейсов C/C++ sqlite3_bind ().
Эти интерфейсы включают базовые типы (строки, числа, BLOB-объекты), но не такие функции, как datetime
,
Один из способов добиться того, что вам нужно, - предоставить смещение в unixepoch
или же julianday
s, и переформатировать запрос, чтобы сделать арифметическое вычитание.
Однако первая параметризованная версия, которую вы показали, должна работать; это делает в Lua:
> db = sqlite3.open(':memory:')
> db:execute'create table t (d);'
> db:execute"insert into t values ('2013-12-26 14:20:00');"
> st = db:prepare "select * from t where d < datetime('now',?);"
> st:bind(1,'+1 day');
> for row in st:urows() do print (row) end
2013-12-26 14:20:00
> st:bind(1,'-1 day');
> for row in st:urows() do print (row) end
>