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

1 投票
1 回答
571 浏览
提问于 2025-04-17 22:21

我在使用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都修复了这个错误。

撰写回答