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

问题描述 投票:0回答:2

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

我没有运行多个执行语句(我知道可能),而是找到了这个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语句执行如下:

插入scheme.newtable,从scheme.oldtable中选择id,data1,data2,data3,其中id为('12345','24567','78945','65423')

相反,我收到以下错误:ORA-01036:非法变量名称/编号

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

python-2.7 cx-oracle
2个回答
1
投票

您可以将executemany()用于批量DML,例如当您想要将大量值插入表中时,作为运行多个insert语句的有效等价物。在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语言接口有各种通用技术,有关可以重写为Python语法的解决方案,请参阅https://oracle.github.io/node-oracledb/doc/api.html#sqlwherein


1
投票

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

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

然后将所选值插入newtable

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中创建临时表的脚本

CREATE GLOBAL TEMPORARY TABLE temp_table
(
  ID  number
);
commit

我希望这很有用。

© www.soinside.com 2019 - 2024. All rights reserved.