【问题标题】:Illegal Variable Name/Number when Passing in Python List传入 Python 列表时的非法变量名称/编号
【发布时间】: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,其中有一些通用解决方案。

标签: python sql oracle cx-oracle


【解决方案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(:d{ind},'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') )
    

    请注意,INlist 为输入列表的每个成员都包含一个绑定变量。

    还要注意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仍然有效。
    猜你喜欢
    • 2013-01-06
    • 2011-10-05
    • 1970-01-01
    • 1970-01-01
    • 2017-03-31
    • 2020-07-29
    • 2016-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多