pro*_*eek 5 python sqlite merge
顺序如下.假设我要合并a.db和b.db. 在命令行中,我执行以下操作.
它运作良好,但在引用的网站中,提问者询问加速,答案是使用'begin'和'commit'命令.
然后,我想出了以下python代码来完成同样的事情.我用SQLiteDB抽象SQLite函数调用,其中一个方法是runCommand().即使我删除了self.connector.commit(),我也得到了同样的错误.
# run command
def runCommand(self, command):
self.cursor.execute(command)
self.connector.commit() # same error even though I delete this line
db = SQLiteDB('a.db')
cmd = "attach \"%s\" as toMerge" % "b.db"
print cmd
db.runCommand(cmd)
cmd = "begin"
db.runCommand(cmd)
cmd = "insert into benchmark select * from toMerge.benchmark"
db.runCommand(cmd)
cmd = "commit"
db.runCommand(cmd)
cmd = "detach database toMerge"
db.runCommand(cmd)
Run Code Online (Sandbox Code Playgroud)
但是,我收到以下错误.
OperationalError: cannot commit - no transaction is active
Run Code Online (Sandbox Code Playgroud)
即使错误,结果db也很好地合并.没有开始/提交,根本就没有错误.
aar*_*ing 12
显然,Cursor.execute不支持'commit'命令.它确实支持'begin'命令,但这是多余的,因为sqlite3会为你开始它们:
>>> import sqlite3
>>> conn = sqlite3.connect(':memory:')
>>> cur = conn.cursor()
>>> cur.execute('begin')
<sqlite3.Cursor object at 0x0104B020>
>>> cur.execute('CREATE TABLE test (id INTEGER)')
<sqlite3.Cursor object at 0x0104B020>
>>> cur.execute('INSERT INTO test VALUES (1)')
<sqlite3.Cursor object at 0x0104B020>
>>> cur.execute('commit')
Traceback (most recent call last):
File "<pyshell#10>", line 1, in <module>
cur.execute('commit')
OperationalError: cannot commit - no transaction is active
>>>
Run Code Online (Sandbox Code Playgroud)
只需commit在Connection对象上使用该方法即可.
至于你的第二个问题,在合并文件时调用begin/commit并不是绝对必要的:只要确保没有磁盘错误,对数据库的修改或在计算机发生错误的情况下查看计算机的人.所以开始/提交可能是一个好主意.当然,如果原始的数据库没有被修改(我老实说没有看过),那么就没有必要.如果出现错误,您可以废弃部分输出并重新开始.
它还提供了加速,因为每次更改都不必在发生时写入磁盘.它们可以存储在内存中并批量写入.但正如上面提到的那样sqlite3.
此外,值得一提的是
cmd = "attach \"%s\" as toMerge" % "b.db"
Run Code Online (Sandbox Code Playgroud)
在它被剥夺的意义上是错误的.如果你想正确地做错事,那就是
cmd = 'attach "{0}" as toMerge'.format("b.db") #why not just one string though?
Run Code Online (Sandbox Code Playgroud)
这与新版本的python向前兼容,这将使移植代码更容易.
如果你想做正确的事,那就是
cmd = "attach ? as toMerge"
cursor.execute(cmd, ('b.db', ))
Run Code Online (Sandbox Code Playgroud)
这避免了sql注入,显然,稍微快一点,所以它是双赢的.
您可以runCommand按如下方式修改方法:
def runCommand(self, sql, params=(), commit=True):
self.cursor.execute(sql, params)
if commit:
self.connector.commit()
Run Code Online (Sandbox Code Playgroud)
现在,commit=False当您不需要提交时,通过传递,您无法在每个命令之后提交.这保留了交易的概念.