Передача параметров Python для предотвращения внедрения SQL. Почему это дает ошибку? - PullRequest
3 голосов
/ 18 февраля 2011
from django.db import connection, transaction

def pk_dt_catalog(p_CAT_ID,p_COMMONS_ID):

    c1 = connection.cursor()
    sql = "SELECT COMMONS_ID, CAT_ID, CAT_NAME 
             FROM DT_CATALOG"

    sql = sql + " WHERE CAT_ID = %s 
                    AND COMMONS_ID = %s "

    param =(p_CAT_ID, p_COMMONS_ID)
    c1.execute(sql, param)
    return c1


>>> c = dt_catalog.pk_dt_catalog(513704,401)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "dt_catalog.py", line 24, in pk_dt_catalog
    c1.execute(sql,(p_CAT_ID, p_COMMONS_ID,))
cx_Oracle.DatabaseError: ORA-01036: illegal variable name/number

1 Ответ

10 голосов
/ 18 февраля 2011

В вашем коде вы используете %s, который является синтаксисом строки подстановки Python, который ожидает значения подстановки в той же строке, например,

sql = sql + " WHERE CAT_ID = %s
                AND COMMONS_ID = %s " % (p_CAT_ID, p_COMMONS_ID)

Однако это (как уже было сказано)не лучший способ, потому что (а) это может быть уязвимость SQL-инъекции;и (b) это, вероятно, приведет к снижению производительности базы данных из-за каждого вызова, требующего жесткого анализа нового оператора SQL.

Вместо этого следует использовать синтаксис переменной Oracle Bind, например:

c1 = connection.cursor()
sql = "SELECT COMMONS_ID, CAT_ID, CAT_NAME 
         FROM DT_CATALOG"

sql = sql + " WHERE CAT_ID = :foo 
                AND COMMONS_ID = :bar "

param = (p_CAT_ID, p_COMMONS_ID)
c1.execute(sql, param)
return c1

Дополнительная информация: http://guyharrison.squarespace.com/blog/2010/1/17/best-practices-with-python-and-oracle.html

В приведенном выше примере используется позиционная привязка, т.е. первый параметр привязан к первому заполнителю привязки, а второй параметр в списке привязан ко второму заполнителю.

Более хороший метод использует dict для присвоения значений определенным переменным связывания по имени.Это полезно, когда трудно узнать порядок, в котором были добавлены заполнители в запрос, и облегчает чтение и сопровождение кода:

c1 = connection.cursor()
sql = "SELECT COMMONS_ID, CAT_ID, CAT_NAME 
         FROM DT_CATALOG"

sql = sql + " WHERE CAT_ID = :foo 
                AND COMMONS_ID = :bar "

param = {"foo": p_CAT_ID, "bar": p_COMMONS_ID}
c1.execute(sql, param)
return c1

Дополнительные примеры и учебные пособия: http://st -curriculum.oracle.com / ОБЕ / дб / 11g / r2 / прод / AppDev / opensrclang / pythonhol2010_db / python_db.htm

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...