Как установить измененный атрибут в переменную в SQL

#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 да, он проверяет запрос на наличие угрозы безопасности, поэтому запросы не должны использовать заполнитель для таблиц и столбцов