python sqlite 3:回滚到保存点失败

1 投票
1 回答
2251 浏览
提问于 2025-04-15 18:46
def rollback_savepoint(self):
    try:
        self.db.execute("rollback to savepoint pt;")
    except:
        print "roll back to save point failed"
    else:
        print "Roll back to save point. Done"
self.db.execute("savepoint pt;")
print "Save point created"

self.cursor.execute("insert into STK values(33)")
self.db.execute("rollback to savepoint pt;")
Save point created
Traceback (most recent call last):
  File "open_db.py", line 77, in <module>
    obj1.save_point()
  File "open_db.py", line 63, in save_point
    self.db.execute("rollback to savepoint pt;")
sqlite3.OperationalError: no such savepoint: pt

在上面的代码片段中,它显示了“回滚到保存点失败”。这是什么意思呢?

补充说明:我把代码改成了下面这样,但却收到了错误信息。

错误

1 个回答

4

不要去捕捉那些你处理不了的错误。让它们直接抛出,这样你才能看到有用的错误信息和追踪记录。

举个例子:

>>> c.execute('rollback to savepoint pt;')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
sqlite3.OperationalError: no such savepoint: pt

从追踪记录中,我可以知道错误是因为没有 pt 保存点。我无法知道你的代码哪里出问题,因为你隐藏了那些最能帮助你的信息。捕捉所有错误然后打印一个“失败”的消息是很傻的——追踪记录更有用,能更好地解释问题。


补充: 你的代码并不是一个容易运行的测试案例,但通过阅读它,我自己写了一些代码来重现这个问题。我还不能准确解释发生了什么,但我找到了一种让它工作的办法——这和 sqlite3模块如何处理事务 有关。

这是我完整的、可以运行的例子:

import sqlite3
from tempfile import NamedTemporaryFile as NF
import os

f = NF(suffix='.db', delete=False).name

db = sqlite3.connect(f)

try:
    db.execute('CREATE TABLE foo (id INTEGER PRIMARY KEY, data VARCHAR)')
    db.isolation_level = None

    db.execute('INSERT INTO foo (data) values (?)', ('hello',))
    db.execute('INSERT INTO foo (data) values (?)', ('world',))

    db.execute("savepoint pt;")
    db.execute('INSERT INTO foo (data) values (?)', ('bah',))
    db.execute('INSERT INTO foo (data) values (?)', ('goodbye world',))
    db.execute("rollback to savepoint pt;")

    db.execute('INSERT INTO foo (data) values (?)', ('peace',))

    assert list(db.execute('select * from foo')) == [(1, 'hello'),
                                                     (2, 'world'),
                                                     (3, 'peace')]
finally:
    db.close()
    os.remove(f)

让它工作的那一行是 db.isolation_level = None。如果你把它注释掉,错误就会像你的一样出现。我尝试了所有文档中提到的值“DEFERRED”、“IMMEDIATE”和“EXCLUSIVE”,结果都出错。

撰写回答