Python sqlite3模块插入记录时返回不正确的rowid值
我在使用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
根据sqlite的文档:
如果一个表包含一个类型为INTEGER PRIMARY KEY的列,那么这个列就会成为ROWID的别名。你可以用四个不同的名字来访问ROWID,包括上面提到的三个原始名字和INTEGER PRIMARY KEY列的名字。
所以在这种情况下,我们应该能得到一个rowid为9999999999,实际上如果我在sqlite3的命令行中运行select last_insert_rowid();
,确实得到了这个值。但是在Python中,我得到的是:
1283723252
或者一些随机的数字,包括负数。这种情况即使在一个干净的新数据库中,只要创建了这个特定的表也会发生。
我使用的是Python 2.6.6,因为我在用它运行一个在SL4A下的脚本。这是一个bug吗?我找不到任何关于这种行为的参考资料。
1 个回答
2
是的,这确实是Python中的一个错误;你可以查看一下 问题17073。任何超过 sys.maxint
的行ID(比如在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都修复了这个错误。