Проблема подстановки параметров SQLite

Используя SQLite3 с Python 2.5, я пытаюсь перебирать список и извлекать вес элемента из базы данных на основе имени элемента.

Я пробовал использовать "?" предлагается подстановка параметров для предотвращения SQL-инъекций, но она не работает. Например, когда я использую:

for item in self.inventory_names:
    self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", item)
    self.cursor.close()

Я получаю сообщение об ошибке:

sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 8 supplied.

Я считаю, что это каким-то образом вызвано первоначальным созданием базы данных; Созданный мной модуль, который фактически создает БД, имеет 8 привязок.

cursor.execute("""CREATE TABLE Equipment 
    (id INTEGER PRIMARY KEY, 
    name TEXT,
    price INTEGER, 
    weight REAL, 
    info TEXT, 
    ammo_cap INTEGER, 
    availability_west TEXT,
    availability_east TEXT)""")

Однако, когда я использую менее безопасную замену «% s» для каждого имени элемента, она работает нормально. Вот так:

for item in self.inventory_names:
    self.cursor.execute("SELECT weight FROM Equipment WHERE name = '%s'" % item)
    self.cursor.close()

Я не могу понять, почему он думает, что у меня 8 привязок, когда я звоню только одному. Как я могу это исправить?

Количество столбцов - это не количество привязок. Количество знаков «?» В запросе - это количество привязок.

S.Lott 23.10.2008 14:38

Да, я знаю. Я просто подумал, что код каким-то образом пытается использовать привязки, на которые ссылается оператор «create table». Я не понимал, что это относится к количеству букв в самом предмете.

crystalattice 23.10.2008 14:58
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
70
2
67 579
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Вы пробовали это? :

for item in self.inventory_names:
    t = (item,)
    self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", t)
    self.cursor.close()

cursor.execute () ожидает последовательность (список, кортеж) в качестве второго параметра. (-> ddaa)

Ответ принят как подходящий

Метод Cursor.execute() ожидает последовательность в качестве второго параметра. Вы предоставляете строку длиной 8 символов.

Вместо этого используйте следующую форму:

self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", [item])

Ссылка на библиотеку Python: sqlite3 Объекты курсора.

Я потратил полдня, пытаясь понять, почему что-то вроде этого выдает мне ошибку:

cursor.execute("SELECT * from ? WHERE name = ?", (table_name, name))

только чтобы узнать, что таблица называет нельзя параметризовать. Надеюсь, это поможет другим сэкономить время.

Вы можете сделать что-то вроде: cursor.execute("SELECT * from %s WHERE name = ?" % table_name, (name,)), хотя это может сделать вашу программу уязвимой для атак SQL-инъекций.

plok 13.10.2011 15:15

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

James 07.12.2011 20:42

@James Мне любопытно, в каких ситуациях вам нужно было изменить таблицу, в которую вы вставляете, на основе пользовательского ввода? Использование dict звучит как довольно хорошая идея для этой ситуации, я использую их всякий раз, когда я использовал бы оператор switch.

num1 05.01.2013 05:16

@ num1: в любое время, когда вы хотите иметь общий класс, который принимает имя таблицы в качестве параметра класса init (). Таким образом, вы не хотите жестко кодировать имя таблицы, но хотите, чтобы оно было переменной ...

staggart 02.01.2016 23:35

Вы используете [] для имен таблиц и полей и ? для значений,

Pete Cacioppi 02.02.2016 05:27

Пришел сюда, ища, как передать несколько аргументов, иди запрос SQLite =)

user8554766 08.06.2018 09:23

Это ограничение SQL, SQLite или Python DB-API?

memilanuk 19.12.2020 18:46

Цитирование (это то, что означают скобки?) с parens, похоже, работает для меня. Я продолжал пытаться (буквально) '?' но я продолжал получать

ProgrammingError: Incorrect number of bindings supplied. The current statement uses 0, and there are 1 supplied.

Когда я это сделал:

SELECT fact FROM factoids WHERE key LIKE (?)

вместо:

SELECT fact FROM factoids WHERE key LIKE '?'

Это сработало.

Это какая-то штука с питоном 2.6?

Если вы используете подстановку параметров sqlite3 (вместо строковой интерполяции Python% s), тогда? вообще не следует цитировать, то есть SELECT fact FROM factoids WHERE key LIKE ?. Просто бывает, что добавление скобок в SQL не меняет смысла, поэтому SELECT fact FROM factoids WHERE key LIKE (?) эквивалентен без ().

Lie Ryan 03.04.2011 21:49

Если вы используете Django и ваш запрос - SELECT fact FROM factoids WHERE key LIKE "%s", вам также следует избегать кавычек. cursor.execute() не распознает% s как привязку в этом запросе. Так что используйте cursor.execute("Select fact FROM factoids WHERE key LIKE %s", (key_name, ))

MrOodles 31.05.2012 20:44

Пытаться

execute("select fact from factoids where key like ?", "%%s%" % val)

Вы вообще ничего не оборачиваете вокруг ?, Python sqlite правильно преобразует его в цитируемый объект.

Аргумент cursor.execute, представляющий значения, которые вам нужно вставить в базу данных, должен быть кортежем (последовательностью). Однако рассмотрите этот пример и посмотрите, что происходит:

>>> ('jason')
'jason'

>>> ('jason',)
('jason',)

В первом примере вместо этого вычисляется строка; поэтому правильный способ представления однозначного кортежа такой же, как во втором вычислении. Во всяком случае, приведенный ниже код исправляет вашу ошибку.

self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", (item,))

Также указание аргументов значения cursor.execute в виде строк (что вы и делаете) приводит к первой оценке в примере и приводит к полученной вами ошибке.

@Kirk, но подстановка параметров не работает для имен таблиц sqlite, поэтому приведенный выше правильный.

rjurney 11.06.2019 18:33

каждый элемент items должен быть кортежем. предполагая, что имена выглядят примерно так:

names = ['Joe', 'Bob', 'Mary']

вам следует сделать следующее:

for item in self.inventory_names:
self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", (item, ))

используя (item,), вы делаете его кортежем вместо строки.

Это вызовет множество запросов. N + 1 проблема.

proofit404 12.12.2019 00:16

У меня как-то есть полная очередь редактирования, поэтому я оставляю комментарий для редактирования. --- функция cursor.execute принимает 3 параметра: строку запроса, список повторяемых элементов, переключатель. здесь список элементов для одного элемента может быть составлен с помощью «[item]» или «(item,)» - принятый ответ - это просто еще одна форма решения, и это еще один @ proofit404

Yılmaz Durmaz 02.11.2020 16:32

Модуль sqlite3 поддерживает виды заполнителей два для параметров:

стиль qmark

Используйте один или несколько ?, чтобы отметить позицию каждого параметра и предоставить список или кортеж параметров. Например.:

curs.execute("SELECT weight FROM Equipment WHERE name = ? AND price = ?",
             ['lead', 24])

названный стиль

Используйте заполнители :par для каждого именованного параметра и укажите dict. Например.:

curs.execute("SELECT weight FROM Equipment WHERE name = :name AND price = :price",
             {name: 'lead', price: 24})

Преимущества именованных параметров стиля в том, что вам не нужно беспокоиться о порядке параметров, и каждый :par можно использовать несколько раз в больших / сложных SQL-запросах.

Как насчет разных параметров стиля? А какой sqlite3 поддерживает и где об этом написано? python.org/dev/peps/pep-0249/#paramstyle

Vladimir Ignatyev 21.03.2020 14:59

Другие вопросы по теме