Получение «sqlite3.OperationalError: нет такого столбца:»

Я новичок в python (как я уверен, вы можете сказать по моему коду) и в основном написал пример сценария для тестирования некоторых основных команд, чтобы я мог лучше понять, как все работает. У меня все работает, как задумано, за исключением последней команды «вставить» - после нескольких часов гугления и экспериментов я не могу понять, что не так, поэтому я был бы признателен, если бы кто-нибудь мог показать мне, что нужно изменить, и помочь мне понять, почему ( Я уверен, что это просто, но я в тупике!).

Ниже приведена строка, которая вызывает у меня затруднения:

c.execute("INSERT OR IGNORE INTO {tn} ({cn1}, {cn2}, {cn3}, {cn4}) VALUES ({VID}, {VSnu}, {VIN}, {VName})".\
        format(tn=table_name, cn1=column1, cn2=column2, cn3=column3, cn4=column4, VID=ID, VSnu=Snu, VIN=IN, VName=Name))

Вот весь сценарий для контекста, если это поможет:

import sqlite3

sqlite_file = '/test_database.sqlite'    # name of the sqlite database   file
table_name = 'test_table'
column1 = 'my_1st_column'
column2 = 'my_2nd_column'
column3 = 'my_3rd_column'
column4 = 'my_4th_column'
ID = int(123456)
Base = 'Arnold'
Snu = 'test'

conn = sqlite3.connect(sqlite_file)
c = conn.cursor()

c.execute("UPDATE {tn} SET {cn2}=('Snu'), {cn3}=('Muh'), {cn4}=('Arnold_A') WHERE {cn1}=({NID})".\
    format(tn=table_name, cn1=column1, cn2=column2, cn3=column3, cn4=column4, NID=ID))

i = 1
while(i<15):
if i == 1: IN = 'B'
if i == 2: IN = 'C'
if i == 3: IN = 'D'
if i == 4: IN = 'E'
if i == 5: IN = 'F'
if i == 6: IN = 'G'
if i == 7: IN = 'H'
if i == 8: IN = 'I'
if i == 9: IN = 'J'

ID = ID+1
i = i+1
Name = Base + '_' + IN
params = (Snu, IN, Name)

c.execute("INSERT OR IGNORE INTO {tn} ({cn1}, {cn2}, {cn3}, {cn4}) VALUES ({VID}, {VSnu}, {VIN}, {VName})".\
        format(tn=table_name, cn1=column1, cn2=column2, cn3=column3, cn4=column4, VID=ID, VSnu=Snu, VIN=IN, VName=Name))

if (i == 10): break

conn.commit()
conn.close()

Он отлично запишет элемент «VID», если он изолирован (это целочисленный столбец и первичный ключ таблицы), но все, что после этого, он интерпретирует как столбец, и я получаю ошибку «нет такого столбца: [значение]». .

Я получаю эту ошибку независимо от того, что идет после «VID» — будь то любая переменная, как показано в приведенной выше команде, или если я пытаюсь вставить прямое строковое значение. Эти другие столбцы являются просто текстовыми столбцами, если это поможет.

Попробуйте '{Vsnu}' или {'Vsnu'} -> строковые литералы в SQL должны быть заключены в одинарные кавычки. Вам следует В самом деле изучить возможность использования параметров для значений запроса.

Mark Benningfield 21.04.2019 02:44
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
1
3 649
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Я знаю, что вы только учитесь, так что не пугайтесь того, что я скажу дальше :-)

Вы неправильно формируете команды SQL. Существует специальная функция, известная как подстановка параметров, которая присутствует во многих API-интерфейсах баз данных, включая SQLite в Python.

Вы не хотите конкатенировать значения, как вы это делаете, потому что это открывает место для чего-то, что называется SQL-инъекцией. В простых сценариях, таких как ваш, это может не быть проблемой, но когда люди делают это в службах, открытых в Интернете, это может нанести большой ущерб (кража данных, потеря данных, повреждение данных и т. д.). Этот комикс иллюстрирует проблему: https://xkcd.com/327/

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

См. пример ниже:

import sqlite3
conn = sqlite3.connect(":memory:")
c = conn.cursor()

# Here we don't need parameter substitution
c.execute("CREATE TABLE mytable (name text, quantity int)")

# We set the values somewhere else. For example, this could come from a web 
# form
entry = ("myname", 2)

# Now we execute the query, with the proper parameter substitution.
# Note the `?` characters. Python will automatically replace those with the 
# values in `entry`, making sure that things are right when forming the 
# command before passing to SQLite.
c.execute("INSERT OR IGNORE INTO mytable VALUES (?, ?)", entry)

print(c.execute("SELECT * from mytable").fetchall())

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

Подробнее здесь: https://docs.python.org/3/library/sqlite3.html

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