繁体   English   中英

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 绑定变量有三种不同的方式,可以在此处看到

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM