Привязка переменной к имени таблицы с помощью cx_Oracle

Я использую cx_Oracle в Python и не могу использовать переменную в качестве имени таблицы, как в этом простом примере:

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

bindvars = {'usertable':usertable}

cursor.execute(query, bindvars)

Каков правильный синтаксис? Подстановка переменных отлично работает, когда я использую WHERE… и т. д., но не с именами таблиц. Думаю, мне нужно как-то отделить ":usertable"...


person tamasgal    schedule 29.10.2012    source источник
comment
Адаптеры базы данных редко поддерживают использование параметров для чего-либо, что не является «значением» (то, что требует кавычек). Либо используйте форматирование строк (хитрый, вы рискуете sql-инъекцией), либо используйте библиотеку, такую ​​​​как SQLAlchemy, которая позволяет вам создавать действительный SQL с использованием кода Python.   -  person Martijn Pieters    schedule 29.10.2012
comment
@septi: я думаю, что использование имени таблицы в качестве переменной связывания невозможно, вам нужно создать динамический оператор, добавив имя таблицы к оператору выбора.   -  person Gaurav Soni    schedule 29.10.2012
comment
Хорошо, спасибо, по крайней мере, я могу перестать тратить свое время ;-) Не могли бы вы добавить ответ, чтобы я мог его принять?   -  person tamasgal    schedule 29.10.2012


Ответы (2)


Адаптеры базы данных редко поддерживают использование параметров для чего-либо, что не является «значением» (то, что требует кавычек). Либо используйте форматирование строк (хитрый, вы рискуете sql-инъекцией), либо используйте библиотеку, такую ​​​​как SQLAlchemy, которая позволяет вам создавать действительный SQL с использованием кода Python.

Если вы уверены, что ваше значение usertable правильное (например, проверено по списку существующих имен таблиц), сработает следующее:

query = 'select * from some.{usertable}.userinfo'.format(usertable=usertable)
person Martijn Pieters    schedule 29.10.2012

Вы не можете привязать имя объекта в 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, или, если все в порядке, продолжайте, как предложил Мартейн.

Я бы рекомендовал прочитать руководство Oracle по защите от SQL-инъекций.

person Ben    schedule 29.10.2012