Проблема подстановки параметров SQLite - PullRequest
55 голосов
/ 23 октября 2008

Используя 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: указано неверное количество привязок. В текущем операторе используется 1, а поставлено 8.

Я полагаю, это как-то вызвано первоначальным созданием базы данных; модуль, который я создал для создания БД, имеет 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 биндинов, когда я звоню только один. Как я могу это исправить?

Ответы [ 8 ]

127 голосов
/ 23 октября 2008

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

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

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

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

51 голосов
/ 28 февраля 2009

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

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

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

23 голосов
/ 05 сентября 2011

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

>>> ('jason')
'jason'

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

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

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

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

2 голосов
/ 23 октября 2008

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

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

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

1 голос
/ 10 февраля 2010

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

ProgrammingError: указано неверное количество привязок. В текущем операторе используется 0, а есть 1.

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

ВЫБРАТЬ ФАКТ ИЗ ФАКТУИДОВ, ГДЕ НАХОДИТСЯ КЛЮЧ (?)

вместо:

ВЫБРАТЬ факт из фактоидов, ГДЕ ключ НРАВИТСЯ '?'

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

Это что-то вроде Python 2.6?

0 голосов
/ 28 июля 2018

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

стиль qmark

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

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

именованный стиль

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

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

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

0 голосов
/ 19 мая 2014

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

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

Вы должны сделать следующее:

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

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

0 голосов
/ 27 июля 2010

Попробуйте

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...