您正在滥用绑定。
可以在这里看到,使用 cx_Oracle 绑定变量有三种不同的方式:
1) 通过将元组传递给带有编号变量的 SQL 语句:
sql = "select * from sometable where somefield = :1 and otherfield = :2"
cur.execute(sql, (aValue, anotherValue))
2) 通过将关键字参数传递给带有命名变量的 SQL 语句:
sql = "select * from sometable where somefield = :myField and otherfield = :anotherOne"
cur.execute(sql, myField=aValue, anotherOne=anotherValue)
3) 通过将字典传递给带有命名变量的 SQL 语句:
sql = "select * from sometable where somefield = :myField and otherfield = :anotherOne"
cur.execute(sql, {"myField":aValue, "anotherOne":anotherValue})
评论
为什么你的代码能工作呢?
让我们试着理解这里发生了什么:
bind= {"var" : "ciao"}
sql = "select * from sometable where somefield = :bind and otherfield = :bind"
cur.execute(sql,(bind["var"], bind["var"]))
Oracle 会理解它需要一个变量。这是一个命名变量,由 name 链接bind
。然后,您应该将参数作为命名参数提供,如下所示:
cur.execute(sql, bind="ciao")
或者使用字典,像这样:
cur.execute(sql, {bind:"ciao"})
但是,当 cx_Oracle 接收到一个元组时,它会在绑定中回退,就像您的 SQL 语句是:
sql = "select * from sometable where somefield = :1 and otherfield = :2"
当你通过bind['var']
两次时,这只是 string "ciao"
。它将两个元组项映射到编号变量:
cur.execute(sql, ("ciao", "ciao"))
这是偶然运行的,但代码非常具有误导性。
具有要绑定的单个值的元组
另请注意,第一个选项需要一个元组。但是,如果您要绑定单个值,则可以使用此表示法创建单个值的元组:
sql = "select * from sometable where somefield = :1"
cur.execute(sql, (aValue,))
[编辑]:感谢@tyler-christian 提到 cx_Oracle 支持传递 dict。