更新表时 cx_Oracle 执行/executemany 错误

Posted

技术标签:

【中文标题】更新表时 cx_Oracle 执行/executemany 错误【英文标题】:cx_Oracle execute/executemany error when updating table 【发布时间】:2020-10-16 06:35:55 【问题描述】:

我需要从我的 Python 代码有条件地更新 Oracle 表。这是一段简单的代码,但我遇到了 cx_Oracle.DatabaseError: ORA-01036: invalid variable name/number 并尝试了以下

id_as_list = ['id-1', 'id-2'] # list of row IDs in the DB table
id_as_list_of_tuples = [('id-1'), ('id-2')] # the same as list of tuples
sql_update = "update my_table set processed = 1 where object_id = :1"

# then when I tried any of following commands, result was "illegal variable name/number" 
cursor.executemany(sql_update, id_as_list) # -> ends with error
cursor.executemany(sql_update, id_as_list_of_tuples)  # -> ends with error
for id in id_as_list:
    cursor.execute(sql_update, id) # -> ends with error

正确的解决方案是在 SQL 语句中使用字典列表和键名:

id_as_list_of_dicts = ['id': 'id-1', 'id': 'id-2'] 
sql_update = "update my_table set processed = 1 where object_id = :id"

cursor.executemany(sql_update, id_as_list_of_dicts)  # -> works
for id in id_as_list_of_dicts:
    cursor.execute(sql_update, id) # -> also works

我找到了一些帮助和教程,例如this,它们都使用“:1, :2,...”语法(但另一方面,我没有找到任何关于 update 和 cx_Oracle 的示例)。虽然我的问题已经在字典的帮助下得到了解决,但我想知道这是否是常见的更新方式,或者我是否在 ":1, :2,..." 语法中做错了什么。

Oracle 12c、Python 3.7、cx_Oracle 7.2.1

【问题讨论】:

你的绑定没问题。您可能还需要预定义内存,如cx-oracle.readthedocs.io/en/latest/user_guide/… 所示 【参考方案1】:

您确实可以绑定字典,但创建字典的开销可能是不可取的。您需要确保在使用executemany() 时创建了一个序列列表。所以在你的情况下,你想要这样的东西:

id_as_list = [['id-1'], ['id-2']] # list of row IDs in the DB table
id_as_list_of_tuples = [('id-1',), ('id-2',)] # the same as list of tuples

首先,您有一个字符串列表。字符串本身就是序列,因此在这种情况下 cx_Oracle 需要 4 个绑定变量(每个字符串中的字符数)。

在第二个实例中,您拥有与第一个实例相同的数据——因为您只是在字符串周围包含括号,而不是创建元组!您需要如我的示例中所示的尾随逗号来创建您认为正在创建的元组!

【讨论】:

以上是关于更新表时 cx_Oracle 执行/executemany 错误的主要内容,如果未能解决你的问题,请参考以下文章

cx_Oracle 连接数据库脚本

查询大型 SQL Server 表时,pymssql/pyodbc 性能(cursor.execute)非常慢

ORA-00942 在 EXECUTE IMMEDIATE 创建表后引用表时出错

在更新 cx_oracle 中的表时出现 DatabaseError: ORA-00933: SQL 命令未正确结束

在 cx_Oracle 上执行许多 CLOB 元素

在kdb中进行回测;在我们解析每一行表时更新/传递表