简体   繁体   English

Python sqlite3:UPDATE失败声称“无此列”

[英]Python sqlite3: UPDATE failure claims “no such column”

The following script evokes the following exception in the UPDATE command. 以下脚本在UPDATE命令中引发以下异常。 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); 我认为对于此简单的UPDATE命令应该发生的事情是db_2.foo.bar的值应该从1翻倍到2。我的猜测是我在UPDATE语句中有一些微妙的语法错误(或者Python上的错误)或sqlite3级别); however, I've pored over the sqlite3 documentation -- especially the "UPDATE" and "expression" pages -- and don't see that I'm doing anything wrong. 但是,我仔细研究了sqlite3文档-尤其是“ UPDATE”和“ expression”页面-并没有发现我做错了什么。

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. 要使用其他表中的值更新foo ,可以使用嵌套的SELECT表达式。 Note that foo.rowid refers to the rowid of the outer table, while t.rowid refers to the rowid of the inner table: 请注意, foo.rowid是指外部表的rowid,而t.rowid是指内部表的rowid:

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 : 要测试适当rowids确实被匹配在一起,我修改您的代码有点所以rowidsdb_1.foo不匹配rowidsdb_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: 注意foorowids是1和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: 注意rowidsdb_1.foo是2和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. UPDATE之后,rowid = 1的行未更改,而rowid = 2的行已更新。

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. 嗯...问题很可能是我在查看3.7.3文档,而我安装的版本是3.6.16。 Investigating. 正在调查。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM