传入 Python 列表时的非法变量名称/编号
Posted
技术标签:
【中文标题】传入 Python 列表时的非法变量名称/编号【英文标题】:Illegal Variable Name/Number when Passing in Python List 【发布时间】:2022-01-12 15:53:26 【问题描述】:我正在尝试通过 Python 在列表上运行 SQL 语句。 通过传入一个列表,在这种情况下是日期。因为我想运行多个 SELECT SQL 查询并返回它们。 我通过传入整数对此进行了测试,但是当尝试传入日期时,我收到 ORA-01036 错误。非法变量名称/编号。我正在使用 Oracle 数据库。
cursor = connection.cursor()
date = ["'01-DEC-21'", "'02-DEC-21'"]
sql = "select * from table1 where datestamp = :date"
for item in date:
cursor.execute(sql,id=item)
res=cursor.fetchall()
print(res)
有什么建议可以运行吗?
【问题讨论】:
用IN代替=,=代表一个值,IN代表列表 @AhmedSunny 感谢您提供此信息。它是一个更大的表,有时使用 IN 解析比一次运行一个需要更长的时间 阅读 cx_Oracle 文档Binding Multiple Values to a SQL WHERE IN Clause,其中有一些通用解决方案。 【参考方案1】:您不能命名绑定变量date
,这是一个非法名称。此外,cursor.execute
中的命名变量应与绑定变量名称匹配。尝试类似:
sql = "select * from table1 where datestamp = :date_input"
for item in date:
cursor.execute(sql,date_input=item)
res=cursor.fetchall()
print(res)
【讨论】:
【参考方案2】:对您的方法的一些建议和警告:
你不应该依赖你的默认NLS
日期设置,同时将String
(例如"'01-DEC-21'"
)绑定到DATE
列。 (您可能还需要重新引用其中一个引号)。
如果您可以在一个查询中获取数据(使用IN
列表),您应该省略在循环中获取数据
使用准备好的语句
示例
date = ['01-DEC-21', '02-DEC-21']
这会为您的输入列表生成使用绑定变量的查询
in_list = ','.join([f" TO_DATE(:dind,'DD-MON-RR','NLS_DATE_LANGUAGE = American')" for ind, d in enumerate(date)])
sql_query = "select * from table1 where datestamp in ( " + in_list + " )"
sql_query
生成的是
select * from table1 where datestamp in
( TO_DATE(:d0,'DD-MON-RR','NLS_DATE_LANGUAGE = American'), TO_DATE(:d1,'DD-MON-RR','NLS_DATE_LANGUAGE = American') )
请注意,IN
list 为输入列表的每个成员都包含一个绑定变量。
还要注意to_date
的使用,带有显式掩码并修复语言以避免月份缩写的解释问题。 (例如 ORA-01843: not a valid month
)
现在您可以使用查询一次性获取数据
cur.prepare(sql_query)
cur.execute(None, date)
res = cur.fetchall()
【讨论】:
感谢您的意见。我已经修改了,现在我得到了cx_Oracle.DatabaseError: ORA-01830: date format picture ends before converting entire input string
由于 Oracle 有一个 statement cache,因此显式的 prepare()
可能没有什么好处
这是真的,并且 光标缓存 工作正常@ChristopherJones。所以在这个简单的例子中不会有 visible 效果。无论如何,IMO 建议在大规模应用程序中使用prepared statements仍然有效。以上是关于传入 Python 列表时的非法变量名称/编号的主要内容,如果未能解决你的问题,请参考以下文章