我在Python中使用cx_Oracle并且无法将变量用作表名,就像在这个简单的例子中一样:
query = "select * from some.:usertable.userinfo"
bindvars = {'usertable':usertable}
cursor.execute(query, bindvars)
正确的语法是什么?当我使用WHERE
...等但不使用表名时,变量替代工作正常。我想我必须以某种方式将“:usertable”分开......
答案 0 :(得分:1)
数据库适配器很少支持将参数用于任何非“值”的东西(需要引用的东西)。要么使用字符串格式化(狡猾,你冒着sql注入的风险),要么使用类似SQLAlchemy的库,让你使用Python代码生成有效的SQL。
如果您确定您的usertable
值是合理的(例如,根据现有表名列表进行检查),则以下内容将起作用:
query = 'select * from some.{usertable}.userinfo'.format(usertable=usertable)
答案 1 :(得分:1)
您无法在Oracle中绑定对象名称,只能绑定文字。但是,Oracle确实有一个内置的包dbms_assert
,以帮助在使用动态对象名时防止SQL注入。您案例中最有用的功能可能是sql_object_name
,其中:
“...验证输入参数字符串是否为合格的SQL 现有SQL对象的标识符。“
例如,您可以在cx_Oracle中执行以下操作。
object_name = cursor.callfunc('sys.dbms_assert.sql_object_name'
, cx_Oracle.string, ['usertable'])
它会引发ORA-44002,如果名称无效,你can capture in cx_Oracle,或者如果一切正常,就像Martijn建议的那样继续。
我建议阅读Oracle guarding against SQL injection指南。