Python cx_Oracle 绑定变量

Python cx_Oracle bind variables

我是Python新手,我在使用绑定变量时遇到了麻烦。如果我执行下面的代码,一切正常。

bind= {"var" : "ciao"}
sql = "select * from sometable where somefield = :bind"
cur.prepare(sql)
cur.execute(sql,bind)

相反,如果我添加另一个绑定变量,则会出现错误。

bind= {"var" : "ciao"}
sql = "select * from sometable where somefield = :bind and otherfield = :bind"
cur.prepare(sql)
cur.execute(sql,(bind,bind))

cur.execute(sql,(bind,bind))
Oracle.NotSupportedError: Variable_TypeByValue(): unhandled data

我已经用

解决了
cur.execute(sql,(bind["var"],bind["var"]))

但是我不明白为什么之前的指令不行

绑定变量的正确使用方法是什么?我正在使用 cx_Oracle.

您滥用了绑定。

与 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.

支持通过字典

@ffarquest 说 cx_Oracle 不支持使用字典,但实际上,@giovanni-de-ciantis 只是使用不当。


named_params = {'dept_id':50, 'sal':1000}
query1 = cursor.execute(
    'SELECT * FROM employees WHERE department_id=:dept_id AND salary>:sal',
    named_params
)

query2 = cursor.execute(
    'SELECT * FROM employees WHERE department_id=:dept_id AND salary>:sal',
    dept_id=50,
    sal=1000
)

在给定的示例中,我认为对 :bind 的第二个引用需要替换为不同的内容,因为它不是按顺序完成的。此外,将变量重命名为 bind 以消除混淆。

bind_dict = {bind:"var" : diff:"ciao"}
sql = "select * from sometable where somefield=:bind and otherfield=:diff"
cur.prepare(sql)
cur.execute(sql, bind_dict )

这篇文章来自 2007 年,展示了您可以使用字典: http://www.oracle.com/technetwork/articles/dsl/prez-python-queries-101587.html