2

我在 Python 中使用 cx_Oracle 并且无法将变量用作表名,就像在这个简单的示例中一样:

query = "select * from some.:usertable.userinfo"

bindvars = {'usertable':usertable}

cursor.execute(query, bindvars)

什么是正确的语法?当我使用...等时,变量替换工作正常,WHERE但不适用于表名。我想我必须以某种方式分隔“:usertable”......</p>

4

3 回答 3

3

数据库适配器很少支持对不是“值”的任何东西(需要引用的东西)使用参数。要么使用字符串格式(狡猾,你冒着 sql 注入的风险),要么使用像 SQLAlchemy 这样的库,让你使用 Python 代码生成有效的 SQL。

如果您确定您的usertable值是合理的(例如,根据现有表名列表检查),则以下内容将起作用:

query = 'select * from some.{usertable}.userinfo'.format(usertable=usertable)
于 2012-10-29T15:54:49.237 回答
2

您不能在 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,您可以在 cx_Oracle 中捕获它,或者如果一切正常,请按照 Martijn 的建议继续。

我建议阅读 Oracle 的防止 SQL 注入指南。

于 2012-10-29T18:11:46.063 回答
0

也许回复有点晚了,但我两天前正在处理同样的事情。

正如 Martjin 所说,解决方案是格式化查询。

query = f'select * from {tableName}'

希望它能帮助别人,因为它帮助了我。

于 2021-10-18T12:54:02.893 回答