我有一个Sqlite3表,其中LastUpdated
列包含格式为"2013-12-24 07:11:21"
的UTC日期时间,并且该表中的所有行都在2天前更新。
我想编写一个SELECT
语句,只返回一段时间内未更新的行:
SELECT LastUpdated FROM UserToken WHERE DATETIME(LastUpdated) < DATETIME('now', '-4 days');
我正在尝试使用sqlite3标准库从Python运行此查询,我希望过时的时间段是可变的。为了安全起见,我尝试使用sqlite3 standard lib documentation中提到的参数替换来使用变量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行,而不是所有行的预期结果。
当我重新启动计算机时,第一次看起来查询工作正常,但是如果我运行带有一个delta值的python脚本,只要我更改delta值,结果就会继续为运行查询的第一个实例。此外,如果我写两个SELECT语句,其中query1设置为'-4 days'
,它应该不返回'-1 days'
处的{2}返回所有行,然后在运行脚本一次后,我切换那些值查询时,查询的输出不会切换。
我认为这可能是不正确的SQL查询,所以我尝试硬编码增量并在Sqlite3 shell中运行查询。正如我期望的那样工作,所以查询没有错。
然后我尝试将变量stale_delta_parameter
从'-n days'
展开到DATETIME('now', '-n days')
,以防参数替换在Sqlite的特殊DATETIME()
函数中无法正常工作。奇怪的行为没有改变。
在Sqlite3标准库或Python DB-API中是否存在某种缓存,可能会阻止更新传递给底层数据库的查询?
我在文档中找不到任何东西,但这是我能想出的唯一理论,似乎符合这种行为。
我试图找到一种方法来打印从Python传递到db的已组装查询,因此我可以验证db没有获得查询的更新版本,但我找不到任何类型的查询从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
答案 0 :(得分:1)
来自SQLite documentation:
“variable”或“parameter”标记在表达式中为使用sqlite3_bind()C / C ++接口系列填充的值指定占位符。
这些接口包括基本类型(字符串,数字,blob),但不包括datetime
等函数。
实现目标的一种方法是在unixepoch
或julianday
中提供偏移量,并重新格式化查询以进行算术减法。
但是,您展示的第一个参数化版本应该可行;它在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
>