我有一个 Oracle SQL 查询:
SELECT * from table1 WHERE deliveredDate = ? AND productID IN (?,?,?,...);
我想使用 cx_Oracle 和 Python 将单个变量传递给 deliveredDate 和一个长度未知的列表
来自 Oracle 使用绑定指南 (https://cx-oracle.readthedocs.io/en/latest/user_guide/bind.html) 我知道您可以绑定单个变量或项目列表,但我'我不确定我们是否可以绑定两者。
请帮我解决这个问题。
谢谢。
当然可以,但是将绑定变量的符号从
?
转换为 :
前面的整数,例如
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)
您问题的关键部分是 IN 子句的“未知长度”。 cx_Oracle 文档Binding Multiple Values to a SQL WHERE IN Clause 显示了各种解决方案,每个解决方案都有一些优缺点,具体取决于列表的大小和语句将执行的次数。在大多数情况下,由于性能影响,您不希望绑定到语句 IN 列表中的单个占位符。如果 IN 列表的大小有上限,则放置那么多的占位符并为所有未知值绑定 None。文档示例更好地解释了它:
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)
(这使用关键字参数来匹配绑定占位符,但您可以改用列表)。
其他解决方案显示在该文档链接中。
您可以使用连接方式通过分隔符分割字符串。你只需要传递一个变量,一个像 '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
)