关于在python的sqlite3中创建表和事务的问题

时间:2015-06-10 15:37:23

标签: python sqlite

我正在学习sqlite3在python中使用sqlite。

应该在关闭连接之前调用诸如insert,update support support transaction和commit()之类的SQL操作,否则数据库中什么都不会改变。但是,'create table'不支持事务,或者create table是自动提交的。例如,

con.execute('create table xxx (xxxx)')

该表将立即创建。更重要的是,如果我们在创建表之前执行insert语句,而不使用commit()。然后执行create table,将提交insert,以及'create table'。

我在文档https://docs.python.org/2/library/sqlite3.html#sqlite3-typeshttps://www.python.org/dev/peps/pep-0249/#id3https://sqlite.org/atomiccommit.html中未发现有关此类行为的任何提及。

我的问题是: 1.有没有其他操作像这样? 2.其他DBMS的行为是什么? 3.有没有关于此的规范?

2 个答案:

答案 0 :(得分:3)

这种行为既不是来自SQLite(像CREATE TABLE这样的命令在事务中完美地工作),也不是来自Python;它是Python sqlite3模块,它试图变得聪明并在某些地方插入自动事务。

这是documented,但给出的理由相当脆弱:

  

这样做有两个原因。首先,其中一些命令在事务中不起作用。

如果模块不会自动启动事务,则不需要在这些命令之前关闭它们。

  

另一个原因是sqlite3需要跟踪事务状态(如果事务处于活动状态)。

如果模块不会自动启动事务,则不需要跟踪事务状态

请注意,在所有情况下,DML语句的检测都无法正常工作。

我建议您通过清除isolation_level来禁用所有这些疯狂。

答案 1 :(得分:0)

这在过去几年中有所改变。

在3.6版中进行了更改:sqlite3用于在DDL语句之前隐式提交一个打开的事务。情况不再如此。

让我们举一个下面的例子:

#!/usr/bin/python

import sqlite3
import sys

try:
    con = sqlite3.connect('test.db')
    cur = con.cursor()
    cur.execute("DROP TABLE IF EXISTS friends")
    cur.execute("CREATE TABLE friends(id INTEGER PRIMARY KEY, name TEXT)")
    cur.execute("INSERT INTO friends(name) VALUES ('Tom')")
    cur.execute("INSERT INTO friends(name) VALUES ('Rebecca')")
    cur.execute("INSERT INTO friends(name) VALUES ('Jim')")
    cur.execute("CREATE TABLE temp(int id)")
    cur.execute("INSERT INTO friends(nam) VALUES ('Robert')")

    con.commit()

except sqlite3.Error as e:

    if con:
        con.rollback()

    print(f'Error {e.args[0]}:')
    sys.exit(1)

finally:

    if con:
        con.close()

最后一个INSERT语句中有错误;列名错误。 friends表已创建,未插入行,并且temp 表未创建。因此DDL CREATE TABLE不再提交open 交易。

但是为什么创建friends表?这是因为Python sliqte3模块 仅针对DML语句(即INSERT / UPDATE / DELETE / REPLACE)启动新事务。