The following script evokes the following exception in the UPDATE command. What I think should happen for this simple UPDATE command is that the value of db_2.foo.bar should be doubled from 1 to 2. My guess is that I have some subtle syntax error in the UPDATE statement (or else a bug at the Python or sqlite3 level); however, I've pored over the sqlite3 documentation -- especially the "UPDATE" and "expression" pages -- and don't see that I'm doing anything wrong.
db_1.foo_bar= (1,)
Traceback (most recent call last):
File "try2.py", line 29, in <module>
db_2.execute( 'UPDATE foo SET bar = bar + db_1.foo.bar WHERE rowid = db_1.foo.rowid' )
sqlite3.OperationalError: no such column: db_1.foo.bar
Any suggestions or workarounds?
import sqlite3
# Create db_1, populate it and close it:
open( 'db_1.sqlite', 'w+' )
db_1 = sqlite3.connect( 'db_1.sqlite' )
db_1.execute( 'CREATE TABLE foo(bar INTEGER)' )
db_1.execute( 'INSERT INTO foo (bar) VALUES (1)' )
db_1.commit()
db_1.close()
# Create db_2:
open( 'db_2.sqlite', 'w+' )
db_2 = sqlite3.connect( 'db_2.sqlite' )
db_2.execute( 'CREATE TABLE foo(bar INTEGER)' )
# Attach db_1 to db_2 connection:
db_2.execute( 'ATTACH "db_1.sqlite" AS db_1' )
# Populate db_2 from db_1:
db_2.execute( 'INSERT INTO foo SELECT ALL * FROM db_1.foo' )
# Show that db_1.foo.bar exists:
cur_2 = db_开发者_运维知识库2.cursor()
cur_2.execute( 'SELECT bar from db_1.foo' )
for result in cur_2.fetchall():
print 'db_1.foo_bar=', result
# However, the following claims that db_1.foo.bar does not exist:
db_2.execute( 'UPDATE foo SET bar = bar + db_1.foo.bar WHERE rowid = db_1.foo.rowid' )
db_2.execute( 'DETACH db_1')
db_2.commit()
db_2.close()
To update foo
with values from a different table, you can use a nested SELECT expression. Note that foo.rowid
refers to the rowid of the outer table, while t.rowid
refers to the rowid of the inner table:
cur_2.execute( '''\
UPDATE foo SET bar = bar +
IFNULL( (SELECT t.bar
FROM db_1.foo AS t
WHERE foo.rowid = t.rowid), 0)''' )
To test that the proper rowids
are indeed being matched together, I modified your code a bit so the rowids
of db_1.foo
do not match the rowids
of db_2.foo
:
import sqlite3
# Create db_1, populate it and close it:
open( 'db_1.sqlite', 'w+' )
db_1 = sqlite3.connect( 'db_1.sqlite' )
db_1.execute( 'CREATE TABLE foo(bar INTEGER)' )
db_1.execute( 'INSERT INTO foo (rowid,bar) VALUES (2,1)' )
db_1.execute( 'INSERT INTO foo (rowid,bar) VALUES (3,2)' )
db_1.commit()
db_1.close()
# Create db_2:
open( 'db_2.sqlite', 'w+' )
db_2 = sqlite3.connect( 'db_2.sqlite' )
cur_2 = db_2.cursor()
cur_2.execute( 'CREATE TABLE foo(bar INTEGER)' )
# Attach db_1 to db_2 connection:
cur_2.execute( 'ATTACH "db_1.sqlite" AS db_1' )
# Populate db_2 from db_1:
cur_2.execute( 'INSERT INTO foo SELECT * FROM db_1.foo' )
Note the rowids
of foo
are 1 and 2:
cur_2.execute( 'SELECT rowid,bar from foo' )
for result in cur_2.fetchall():
print('foo: {0}'.format(result))
# foo: (1, 1)
# foo: (2, 2)
Note the rowids
of db_1.foo
are 2 and 3:
# Show that db_1.foo.bar exists:
cur_2.execute( 'SELECT rowid,bar from db_1.foo' )
for result in cur_2.fetchall():
print('db_1.foo: {0}'.format(result))
# db_1.foo: (2, 1)
# db_1.foo: (3, 2)
cur_2.execute( '''\
UPDATE foo SET bar = bar +
IFNULL( (SELECT t.bar
FROM db_1.foo AS t
WHERE foo.rowid = t.rowid), 0)''' )
After the UPDATE, the row with rowid = 1 has not changed, while the row with rowid = 2 has been updated.
cur_2.execute( 'SELECT rowid,bar from foo' )
for result in cur_2.fetchall():
print('foo after update: {0} '.format(result))
# foo after update: (1, 1)
# foo after update: (2, 3)
cur_2.execute('DETACH db_1')
db_2.commit()
db_2.close()
I found these pages helpful in constructing this answer: here and here, though any mistakes are of course my own.
Hmmm... the problem may very well be that I am looking at the 3.7.3 documentation, whereas my installed version is 3.6.16. Investigating.
精彩评论