Python sqlite3模块在插入记录时返回不正确的rowid值

时间:2014-03-14 17:39:18

标签: python sqlite

我在Python的sqlite3模块中遇到了一个非常奇怪的问题 - 更奇怪的是,它只出现在一个特定的表中,但它出现在该表中,无论它在哪个数据库中。

因此,我在sqlite3数据库中创建了一个表,其中包含以下内容:

CREATE TABLE BlockedNumbers (MobileNumber integer PRIMARY KEY NOT NULL, BlockedTimes integer);

然后在Python中运行:

import sqlite3
conn = sqlite3.connect('/tmp/test.db',isolation_level=None, detect_types=sqlite3.PARSE_DECLTYPES);
sqliteobj = conn.cursor()
sqliteobj.execute("INSERT INTO BlockedNumbers (MobileNumber,BlockedTimes) VALUES ('9999999999','1');")
print sqliteobj.lastrowid

根据the sqlite documentation

  

如果表包含INTEGER PRIMARY KEY类型的列,则该列将成为ROWID的别名。然后,您可以使用四个不同的名称中的任何一个来访问ROWID,上面描述的原始三个名称或给予INTEGER PRIMARY KEY列的名称。

所以在这种情况下,我们希望得到一个9999999999的rowid,而且这正是我在sqlite3 shell中运行select last_insert_rowid();所得到的。但在Python中我得到:

1283723252

或各种随机数,包括负数。如果创建了这个特定的表,即使使用干净的新数据库也会发生这种情况。

这是我运行的Python 2.6.6,因为我使用的是在SL4A下运行的脚本。这是一个错误吗?我无法找到任何对此类行为的引用。

1 个答案:

答案 0 :(得分:2)

是的,这是Python中的一个错误;见issue 17073。超过sys.maxint的任何rowid(例如64位系统上的2147483647)都会溢出:

$ python
Python 2.6.6 (r266:84292, Dec 27 2010, 00:02:40) 
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> import sqlite3
>>> conn = sqlite3.connect(':memory:')
>>> sqliteobj = conn.cursor()
>>> sqliteobj.execute('CREATE TABLE BlockedNumbers (MobileNumber integer PRIMARY KEY NOT NULL, BlockedTimes integer);')
<sqlite3.Cursor object at 0xb73fb7a0>
>>> sqliteobj.execute("INSERT INTO BlockedNumbers (MobileNumber,BlockedTimes) VALUES (?, '1')", (sys.maxint,))
<sqlite3.Cursor object at 0xb73fb7a0>
>>> sqliteobj.lastrowid
2147483647
>>> sqliteobj.execute("INSERT INTO BlockedNumbers (MobileNumber,BlockedTimes) VALUES (?, '1')", (sys.maxint + 1,))
<sqlite3.Cursor object at 0xb73fb7a0>
>>> sqliteobj.lastrowid
-2147483648

Python版本2.6.9,2.7.4,3.2.4和3.3.1都包含此错误的修复程序。