Ошибка программирования с pyodbc 42601] ОШИБКА: синтаксическая ошибка рядом с "***";\nОшибка

Вопрос или проблема

Я хочу распарсить данные из xml, но когда я пытаюсь вставить эти данные в базу данных SQL через db_cursor.execute, я получаю ошибку, потому что у меня есть некоторые данные с одинарными и двойными кавычками в одном столбце:

import re
import os
import pyodbc
import xml.etree.ElementTree as ET
login_db = '\*\*\*\*\*'
passwd_db ='\*\*\*\*\*\*\*'
db_str = ("Driver={PostgreSQL UNICODE(x64)};"
"Server=\*\*\*\*\*\*\*;"
"Port=5432;"
"Database=inventory_UAT;"
"Uid=%s;"
"Pwd=%s") % (login_db, passwd_db)
db_cnxn = pyodbc.connect(db_str,autocommit=True)
db_cnxn.setdecoding(pyodbc.SQL_WCHAR, encoding='utf-8')
db_cnxn.setencoding(encoding='utf-8')
db_cursor = db_cnxn.cursor()
import xml.etree.ElementTree as ET
tree1 = ET.parse(r"C:\\Mine\\diverts.xml")
root1 = tree1.getroot()
for div in root1.findall('{urn:activemq:core}divert'):
source = div.find('{urn:activemq:core}address').text
target = div.find('{urn:activemq:core}forwarding-address').text
name = div.attrib\['name'\]
filtr = ""
for i in div.findall('{urn:activemq:core}filter'):
filtr = i.attrib\['string'\]
qry = (("""INSERT INTO inventory.artemis_divert_inventory
(divert_name,from_address,to_address,filter,instance_type,last_update)
VALUES ('%s','%s','%s','%s','CORP-UAT',NOW());""")
%(name, source, target, filtr))  
\# print(qry)
db_cursor.execute(qry)

Вот ошибка:
pyodbc.ProgrammingError: (‘42601’, ‘[42601] ERROR: syntax error at or near “KondorSDEvent_uat1”;\nОшибка при выполнении запроса (1) (SQLExecDirectW)’)

Позвольте мне добавить некоторые из этих данных в столбец фильтра:
_AMQ_ORIG_ADDRESS is null and (MessageType=”CommodityReset” or (MessageType=”Product” and ProductTy
pe=”Commodity”
Publisher IN (‘KondorSDEvent_uat1′,’AdstisSDEvent_uat1’)

Я вообще не знаю, как решить эту проблему

Ответ или решение

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

Причина проблемы

В вашем коде динамически создается SQL-запрос, который включает значения, полученные из XML-данных. Когда эти значения содержат одинарные кавычки, они нарушают синтаксис SQL. Например, строка:

Publisher IN ('KondorSDEvent_uat1','AdstisSDEvent_uat1')

Если filtr содержит подобную строку с кавычками, SQL-запрос становится недопустимым.

Рекомендации по решению проблемы

1. Использование параметризованных запросов

Наиболее безопасный и правильный подход — использовать параметризованные запросы. Это не только помогает избежать проблем с синтаксисом, но и повышает безопасность за счет предотвращения SQL-инъекций. Вместо формирования запроса в виде форматированной строки, используйте вопросительные знаки в качестве плейсхолдеров:

qry = """INSERT INTO inventory.artemis_divert_inventory
(divert_name, from_address, to_address, filter, instance_type, last_update)
VALUES (?, ?, ?, ?, 'CORP-UAT', NOW());"""
params = (name, source, target, filtr)
db_cursor.execute(qry, params)

2. Экранирование строк

Если по какой-то причине не удается использовать параметризованные запросы, необходимо экранировать одинарные кавычки в строках, заменяя их на две одинарные кавычки:

filtr = filtr.replace("'", "''")

Однако выполнение этого подхода менее предпочтительно, поскольку оно может быть подвержено ошибкам, особенно в случае более сложных строк.

3. Проверка корректности данных

Также имеет смысл проверять данные, которые вы извлекаете из XML, и убедиться, что они не содержат неподходящих символов, если вы не контролируете входные данные. Например, вы можете добавить логику для обработки или фильтрации данных перед их вставкой в базу данных.

Пример исправленного кода

Вот пример вашего кода с использованием параметризованных запросов:

import pyodbc
import xml.etree.ElementTree as ET

login_db = '*****'
passwd_db = '******'
db_str = ("Driver={PostgreSQL UNICODE(x64)};"
          "Server=********;"
          "Port=5432;"
          "Database=inventory_UAT;"
          "Uid=%s;"
          "Pwd=%s") % (login_db, passwd_db)
db_cnxn = pyodbc.connect(db_str, autocommit=True)
db_cnxn.setdecoding(pyodbc.SQL_WCHAR, encoding='utf-8')
db_cnxn.setencoding(encoding='utf-8')
db_cursor = db_cnxn.cursor()

tree1 = ET.parse(r"C:\\Mine\\diverts.xml")
root1 = tree1.getroot()

for div in root1.findall('{urn:activemq:core}divert'):
    source = div.find('{urn:activemq:core}address').text
    target = div.find('{urn:activemq:core}forwarding-address').text
    name = div.attrib['name']
    filtr = ""
    for i in div.findall('{urn:activemq:core}filter'):
        filtr = i.attrib['string']

    # Параметризованный запрос
    qry = """INSERT INTO inventory.artemis_divert_inventory
             (divert_name, from_address, to_address, filter, instance_type, last_update)
             VALUES (?, ?, ?, ?, 'CORP-UAT', NOW());"""
    params = (name, source, target, filtr)
    db_cursor.execute(qry, params)

Заключение

Использование параметризованных запросов — это наилучший и наиболее безопасный способ обработки SQL-запросов в вашем приложении. Это позволяет избежать ошибок синтаксиса и снижает риск SQL-инъекций, что особенно важно для обеспечения безопасности ваших данных и систем.

Оцените материал
Добавить комментарий

Капча загружается...