Как сформировать SQL запрос с русскими символами в выражениях?

Требуется сформировать SQL запрос, где в WHEREвыражении содержатся русские символы.

sap_code = 'ОВОЩИ – ФРУКТЫ'
sql_string = 'SELECT ' \
            'SAP_CODE, ' \
            'SKU, ' \
        'FROM INFO ' \
        f'WHERE ROWNUM < {settings.NQ_SQL_LIMIT}'
if sap_code:
    sql_string += f' AND SAP_CODE = {sap_code}'
with connections[db].cursor() as cursor:
    exec_result = cursor.execute(
        sql_string
    )

Но выдает такую ошибку:

django.db.utils.DatabaseError: ORA-00911: invalid character`

Как это можно исправить?


Ответы (1 шт):

Автор решения: 0xdb

Символьные значения надо заключать в одиночные кавычки, в данном случае:

AND SAP_CODE = \'{sap_code}\'

Но включать значения переменных непосредственно в запрос ни в коем случае не следует (см. пояснение ниже). Передавайте их как переменные связывания.
Вот воспроизводимый пример, как надо сделать:

from cx_Oracle import connect 

conn = connect ('me/pass@srv/pdb1', encoding="utf-8")
curs = conn.cursor ()
code = 'ОВОЩИ'
rown = 1
text = '''
    select * from (
        select :1 code from dual)
    where rownum <= :2 and code = :1'''
curs.execute (text, (code, rown))
rows = curs.fetchall ()
conn.close ()
print (rows)

Результат:

[('ОВОЩИ',)]

почему не следует включать в запрос значения переменных напрямую?

Пример того, как делать не надо:

query = f"SELECT * FROM tab WHERE code = '{code}'"

По нескольким причинам:

  • Чтобы обезопасить себя от SQL Injections.
  • Чтобы не "засорять" Library Cache похожими запросами, отличающимися только значением литерала.
  • Запрос вида SELECT * FROM tab WHERE code = :1 будет парситься (hard parse) только первый раз. Это дополнительно сэкономит время на парсинг.
→ Ссылка