您在滥用绑定。
使用 cx_Oracle 绑定变量有三种不同的方式see here:
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 会理解它需要一个变量。这是一个命名变量,通过名称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'] 两次时,这只是字符串"ciao"。它将两个元组项映射到编号变量:
cur.execute(sql, ("ciao", "ciao"))
这是偶然运行的,但代码非常具有误导性。
要绑定单个值的元组
另请注意,第一个选项需要一个元组。但是,如果您要绑定单个值,则可以使用此表示法创建单个值的元组:
sql = "select * from sometable where somefield = :1"
cur.execute(sql, (aValue,))
[编辑]:感谢@tyler-christian 提到 cx_Oracle 支持传递 dict。