Python Cx_Oracle;如何使用列表作为参数执行 SQL 插入

Python Cx_Oracle; How Can I Execute a SQL Insert using a list as a parameter

我生成了一个 ID 号列表。我想执行一个插入语句,从一个 table 中获取所有记录,其中 ID 值在我的列表中,并将这些记录插入另一个 table。

而不是 运行 通过多个执行语句(据我所知是可能的),我发现了这个 cx_Oracle 函数,据说它可以使用单个语句和列表参数执行所有内容。 (它还避免了 SQL 语句在传入参数之前的笨拙格式)但我认为我需要在将其作为参数传入之前更改我的列表。只是不确定如何。

我引用了这个网页: https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-executemany.html

ids = getIDs()
print(ids)

[('12345',),('24567',),('78945',),('65423',)]

sql = """insert into scheme.newtable
     select id, data1, data2, data3
     from scheme.oldtable
      where id in (%s)"""
cursor.prepare(sql)
cursor.executemany(None, ids)

我希望 SQL 语句执行如下:

Insert into scheme.newtable select id, data1, data2, data3 from scheme.oldtable where id in ('12345','24567','78945','65423')

相反,我收到以下错误: ORA-01036: 非法变量 name/number

编辑: 我发现了这个 Whosebug:How can I do a batch insert into an Oracle database using Python? 我更新了我的代码以预先准备语句并将列表项更新为元组,但我仍然遇到相同的错误。

您使用 executemany() 进行批处理 DML,例如当您想将大量值插入 table 作为 运行 多个插入语句的有效等价物时。 https://blogs.oracle.com/opal/efficient-and-scalable-batch-statement-execution-in-python-cx_oracle

中讨论了 cx_Oracle 个示例

但是你在做什么

insert into scheme.newtable
     select id, data1, data2, data3
     from scheme.oldtable
      where id in (%s)

是另一回事 - 您正试图在 IN 子句中使用多个值来执行一个 INSERT 语句。为此,您可以使用普通的 execute()

由于 Oracle 保持绑定数据与 SQL 不同,您不能将多个值传递给单个绑定参数,因为数据被视为单个 SQL 实体,而不是列表值。您可以使用现有的 %s 字符串替换语法,但这对 SQL 注入攻击是开放的。

Oracle 语言接口有多种通用技术,请参阅 https://oracle.github.io/node-oracledb/doc/api.html#sqlwherein 以了解可以重写为 Python 语法的解决方案。

使用临时 table 保存 ID(批量插入)

cursor.prepare('insert into temp_table values (:1)')
dictList = [{'1': x} for x in ids]
cursor.executemany(None, dictList)

然后将选定的值插入新的table

sql="insert into scheme.newtable (selectid, data1, data2, data3 from scheme.oldtable inner join temp_table on scheme.oldtable.id = temp_table.id)"
cursor.execut(sql,connection)

在oracle

中创建临时table的脚本
CREATE GLOBAL TEMPORARY TABLE temp_table
(
  ID  number
);
commit

希望有用。