将单个绑定变量和列表变量同时传递给SQL查询cx_Oracle Python

klr1opcd  于 2023-04-29  发布在  Oracle
关注(0)|答案(3)|浏览(173)

我有一个Oracle SQL查询:

SELECT * from table1 WHERE deliveredDate = ? AND productID IN (?,?,?,...);

我想通过cx_Oracle和Python将一个变量传递给deliveredDate和一个长度未知的productID的列表
从Oracle Using Bind guide(https://cx-oracle.readthedocs.io/en/latest/user_guide/bind.html)中,我了解到您可以绑定单个变量或项目列表,但我不确定是否可以同时绑定两者。
请帮助我解决这个问题。
谢谢大家。

d8tt03nd

d8tt03nd1#

当然可以,但是要将绑定变量的表示法从**?转换为:**-前面是整数,例如

import pandas as pd
import cx_Oracle
import datetime

conn = cx_Oracle.connect('un/pwd@ip:port/db')
cur = conn.cursor()

sql  = """
       SELECT *
         FROM table1
        WHERE deliveredDate = :0 AND productID IN (:1,:2)   
       """
cur.execute(sql,[datetime.datetime(2022, 5, 3),1,2])

res = cur.fetchall()

print(res)
1l5u6lss

1l5u6lss2#

你的问题的关键部分是IN子句的“未知长度”。cx_Oracle文档绑定多个值到SQL WHERE IN子句显示了各种解决方案,每个解决方案都有一些优缺点,具体取决于列表的大小和语句将被执行的次数。在大多数情况下,由于性能问题,您不希望绑定到语句IN列表中的单个占位符。如果IN列表的大小有一个上限,那么就放置那么多的占位符,并为所有未知值绑定None。doc的例子解释得更好:

cursor.execute("""
        select employee_id, first_name, last_name
        from employees
        where last_name in (:name1, :name2, :name3, :name4, :name5)""",
        name1="Smith", name2="Taylor", name3=None, name4=None, name5=None)
for row in cursor:
    print(row)

(This使用关键字参数来匹配绑定占位符,但也可以使用列表)。
其他解决方案显示在文档链接中。

lyfkaqu1

lyfkaqu13#

您可以使用connect by来将字符串拆分通过分隔符。你只需要传递一个变量,一个像 '46083,46092,46093,46096,46098,46111,46119' 这样的字符串。
它也适用于字符串中不断变化的项目编号。
这可能会给SQL增加一点开销,但如果查询运行了几秒钟或更长时间,这并不重要。在我的情况下,它给了大约0,064秒的运行时间与30-60个项目。

select * from MYTABLE where
id in
(
    SELECT regexp_substr( :MYLIST ,'[^,]+', 1, level) myid FROM dual
    CONNECT BY regexp_substr( :MYLIST , '[^,]+', 1, level) IS NOT NULL
)

相关问题