#python #sql #sqlite
Вопрос:
В принципе, чтобы иметь возможность писать меньше функций, я сделал отредактированный атрибут переменной. Итак, мой код редактирования выглядит следующим образом :
cur.execute(""" UPDATE acteurs SET ?=? WHERE IDACTEUR=?; """, (attribute, newvalue, actorid)) conn.commit()
Но при запуске я получаю синтаксическую ошибку. Как я должен отредактировать это, чтобы оно работало?
Комментарии:
1. в некоторых местах вы не можете использовать
?
по соображениям безопасности. Например, вы не можете использовать?
в качестве имени таблицы. И вам, возможно, потребуется ввести некоторые значения с помощьюstring formatting
илиf-string
2. @esqew Может быть, это стандартная замена в SQLite, но Python может заблокировать ее — по соображениям безопасности
3. @esqew Я бы сказал, что проблема может быть в том, что Python может экранировать параметры, чтобы сделать их безопасными. Поэтому вместо
column=value
этого можно создать две строки"column"="value"
, и это неверно в SQL.
Ответ №1:
Python экранирует значения перед вводом запроса — по соображениям безопасности — поэтому значения нельзя использовать в некоторых местах, потому что это создает неправильный запрос.
Использование ?=?
, которое вы ожидаете column=value
, но оно создает две строки "column"="value"
и может привести к ошибке.
Он также может проверить, ?
на месте ли имя таблицы или имя столбца, и вызвать ошибку — по соображениям безопасности.
Возможно, потребуется column
использовать string formatting
или f-string
. Но это не является предпочтительным. Запросы не должны использоваться ?
для имен таблиц, имен столбцов.
Минимальный рабочий пример.
Он используется con.set_trace_callback(print)
для отображения последнего запроса.
import sqlite3 con = sqlite3.connect(":memory:")# con.set_trace_callback(print) cur = con.cursor() cur.execute("CREATE TABLE test(key TEXT, value TEXT)") print('---') cur.execute("INSERT INTO test(key, value) VALUES (?, ?)", ("a", "1")) con.commit() print('---') cur.execute("SELECT key, value FROM test WHERE key=?", ('a',)) row = cur.fetchone() print(row) print('---') cur.execute("SELECT key, value FROM test WHERE ?=?", ('key', 'a')) row = cur.fetchone() print(row) print('---') try: cur.execute("UPDATE test SET ?=? WHERE key=?", ('value', '3', 'a',)) con.commit() except Exception as ex: print('Exception:', ex) print('---') try: column = 'value' cur.execute(f"UPDATE test SET {column}=? WHERE key=?", ('3', 'a',)) con.commit() except Exception as ex: print('Exception:', ex) print('---') cur.execute("SELECT key, value FROM test WHERE key=?", ('a',)) row = cur.fetchone() print(row) print('---') con.close()
Пример WHERE key=?", ('a',)
создается WHERE key='a'
, и он получает одну строку.
Пример WHERE ?=?", ('key', 'a',)
создается WHERE 'key'='a'
, и он получает нулевые строки.
Пример SET ?=?
вызывает ошибку.
CREATE TABLE test(key TEXT, value TEXT) --- BEGIN INSERT INTO test(key, value) VALUES ('a', '1') COMMIT --- SELECT key, value FROM test WHERE key='a' ('a', '1') --- SELECT key, value FROM test WHERE 'key'='a' None --- Exception: near "?": syntax error --- BEGIN UPDATE test SET value='3' WHERE key='a' COMMIT --- SELECT key, value FROM test WHERE key='a' ('a', '3')
Комментарии:
1. Короче говоря, вы не можете использовать замену заполнителей для таких вещей, как имена таблиц и столбцов, так как это создает значительную угрозу безопасности, которую этот тип замены стремится снизить.
2. @esqew да, он проверяет запрос на наличие угрозы безопасности, поэтому запросы не должны использовать заполнитель для таблиц и столбцов