Я создал функцию для создания команд sqlite в python 3.6 из текста, который я собираю с веб-сайтов. Длина команды sql зависит от полученного текста.
def build_sql_stmnt(row, table, col_val):
"""builds an sql_stmnt to query fencers_db1.sqlite
input:
row -- string, row data wanted
table -- string, table to query
col_val -- tuple with column/value pairs
Ex1: (('column', value),)
Ex2: (('column1', value1), ('column2', value2))
returns: sql_stmnt -- string to be used as c.execute SELECT argument
"""
string = ''
countdown = len(col_val)
for pair in col_val:
if countdown > 1:
string = string + ("""{} = '{}' AND """.format(pair[0], pair[1]))
else:
string = string + ("""{} = '{}'""".format(pair[0], pair[1]))
countdown -= 1
sql_stmnt = """SELECT {rw} FROM {tbl} WHERE {s};""".format(
rw = row,
tbl = table,
s = string)
return sql_stmnt
Я прибег к тройным кавычкам для определения строк выше, когда обнаружил, что очищаемый мной текст может включать двойные кавычки ("). Теперь я обнаружил, что текст, который я очищаю, также может включать апострофы ('). Когда я запускаю функцию когда col_val включает апостроф («Клуб фехтовальщиков»), я получаю следующую ошибку:
OperationalError: near "Club": syntax error
Следующее возвращает ту же ошибку:
if countdown > 1:
string = string + ("""{} = \'{}\' AND """.format(p0, p1))
else:
string = string + ("""{} = \'{}\'""".format(p0, p1))
countdown -= 1
Есть ли лучший способ создать оператор sql или есть способ сгенерировать строки с переменными, которые могут содержать двойные кавычки и / или апострофы?






Вы никогда не захотите создавать операторы SQL, вручную цитируя такие вещи.
Почти всегда ответ - использовать параметры SQL. В таких случаях, когда даже имя таблицы является динамической строкой, вы не можете этого сделать.
Вот почему в большинстве библиотек SQL есть функция для вставки значений в кавычки или экранирования вручную. К сожалению, главным исключением является sqlite3.
Итак, вам нужно написать свою собственную функцию экранирования. Как объясняет документы:
A string constant is formed by enclosing the string in single quotes (
'). A single quote within the string can be encoded by putting two single quotes in a row - as in Pascal. C-style escapes using the backslash character are not supported because they are not standard SQL.
Так:
def esc(s):
return "'{}'".format(s.replace("'", "''"))
И теперь вам нужно вручную вызывать его везде, где есть строковое значение:
string = string + ("""{} = '{}' AND """.format(pair[0], esc(pair[1])))
В качестве побочного примечания, вы, кажется, немного запутались в разнице между строковыми литералами и строковыми значениями. Все эти литералы создают идентичную строку формата:
'{} = \'{}\' AND '
"{} = '{}' AND "
"""{} = '{}' AND """
Итак, когда вы вызываете format в этой строке, не имеет значения, с какой из них вы начали. Биты {} просто заменяются содержимым аргументов format. Если в этих аргументах есть кавычки, format просто скопирует кавычки, и ничто из того, что вы можете сделать со строковым литералом для строки формата, не изменит этого. Вам нужно исправить аргументы как строковые значения.
В любом случае, при дальнейшем размышлении, вы, вероятно, используете здесь параметры SQL может - не вместо format, как обычно, а в дополнение к этому. И тогда вы не должны беспокоиться о том, чтобы вручную экранировать вещи, потому что строки, которые вы используете format, не нуждаются в экранировании, а только значения столбцов, которые.
Что вам нужно сделать, так это создать строку плюс список. Например:
whereparams, whereargs = []
for col, val in col_val:
whereparams.append('{} = ?'.format(name))
whereargs.append(val)
whereclause = ', '.join(whereparams)
# ...
sql = '''SELECT {rw} FROM {tbl} WHERE {wc}'''.format(
rw=row, tbl=table, wc=whereclause)
Вы можете выполнить запрос (сейчас или где-то в будущем) следующим образом:
cursor.execute(sql, whereargs)
… Зная, что последовательность whereargs имеет в точности те аргументы, которые соответствуют значениям ? в операторе SQL, в том же порядке.
Первый вариант работает, когда я удаляю одинарные кавычки из строки: def esc(s): return "{}".format(s.replace("'", "''"))
Если вы очищаете мой сайт, и у меня есть значение столбца, такое как
Robert'); DROP TABLE Importantstuff; --, которое обманом заставляет ваш код удалять данные целой таблицы… разве это имеет для вас значение?