sqlite3.OperationalError: нет такой таблицы: my_boardgames, НО ЕГО - PullRequest
0 голосов
/ 02 октября 2019

я пытаюсь записать в таблицу в приложении sqlite через python.

код выглядит следующим образом:


#skapa databasen och koppla till den
import sqlite3
conn = sqlite3.connect('Minna_spel.db')
cursor = conn.cursor()
print("Opened database successfully!!!")

#skapa tabbelerna i databasen

cursor.execute("""CREATE TABLE IF NOT EXISTS my_boardgames 
               (game_name text,
                genre text,
                recage int,
                playtime int,
                players int
                )""")

print("created tabel successfully!!!")
conn.commit()
conn.close()

def add_new_game():
    conn = sqlite3.connect('Minna_spel.db')
    cursor = conn.cursor()

    val_game_name = input("Namn?")
    val_genre = input("Genre?")
    val_rec_age = input("Rekomenderad ålder?")
    val_play_time = input("speltid?")
    val_players = input("Antal Spelare?")

    conn.execute("INSERT INTO my_boardgames (game_name,genre,recage,playtime,players)
VALUES (val_game_name,val_genre,val_rec_age,val_play_time,val_players)");
    print("spelet är nu sparat !")

    conn.commit()
    conn.close()

я не уверен, что я делаю неправильно, но как только я сделаюВо всех входных данных функции add_new_games она завершается ошибкой с помощью инструкции:

sqlite3.OperationalError: sqlite3.OperationalError: нет такого столбца: val_game_name enter image description here

Я отмечаюбаза данных и достаточно уверен, что там. Что я делаю не так?

С наилучшими пожеланиями

1 Ответ

1 голос
/ 02 октября 2019

Примечание: я немного переформатировал текстовые строки для удобства чтения, разделив строки.

Вы не интерполируете значения переменных в строку запроса. Следующая строка

conn.execute(
    "INSERT INTO my_boardgames "
    "(game_name,genre,recage,playtime,players) "
    "VALUES "
    "(val_game_name,val_genre,val_rec_age,val_play_time,val_players)");

Необходимо заменить на

conn.execute(
    "INSERT INTO my_boardgames "
    "(game_name,genre,recage,playtime,players) "
    "VALUES "
    "(?, ?, ?, ?, ?)",
    (val_game_name, val_genre, val_rec_age, val_play_time, val_players));

Дополнительная информация


Как вы упомянули в комментариях, что выначинающий программист, я добавлю больше информации

В следующем коде будут использоваться только два столбца, чтобы сделать строки более короткими и удобочитаемыми.


AНаивный подход

Наиболее очевидным (но неэффективным, подверженным ошибкам и небезопасным) решением будет следующее:

conn.execute(
    "INSERT INTO my_boardgames "
    "(game_name, genre) "
    "VALUES ('" + val_game_name + "', '" + val_genre + "')")

Конкатенация строк затрудняет чтение кода, и вам необходимоиметь дело с правильной ценовой цитатой самостоятельно, что легко ошибиться. Он также очень хрупкий и небезопасный, поскольку определенные значения могут привести к тому, что запрос станет недействительным, или (если он создан злонамеренно) может заставить запрос сделать что-то совершенно другое ( Атака SQL-инъекции ( видео * 1031)*)).

Улучшение читаемости с помощью форматирования строк

Второй подход может привести к следующему, что сделает код более читабельным.

# Using traditional "printf-style" formatting
conn.execute(
    "INSERT INTO my_boardgames "
    "(game_name, genre) "
    "VALUES ('%s', '%s')" % (val_game_name , val_genre))

# Using "new-style" formatting
conn.execute(
    "INSERT INTO my_boardgames "
    "(game_name, genre) "
    "VALUES ('{}', '{}')".format(val_game_name , val_genre))

# Using f-strings
conn.execute(
    "INSERT INTO my_boardgames "
    "(game_name, genre) "
    f"VALUES ('{val_game_name}', '{val_genre}')")

Эти 3 версиивсе технически одно и то же решение. Они заменяют специальные заполнители внутри строки перед тем, как отправит ее в библиотеку базы данных (в данном случае SQLite). Результирующая строка запроса SQL такая же, как и строка, использующая + для объединения строк. Код становится немного более читабельным, но код все еще хрупок и небезопасен по той же причине, что и первый вариант.

Правильный способ сделать это

Это приводит нас к финальномуРешение (в моем первоначальном ответе выше):

# Using "new-style" formatting
conn.execute(
    "INSERT INTO my_boardgames "
    "(game_name, genre) "
    "VALUES (?, ?)", (val_game_name , val_genre))

Есть некоторые тонкие, но важные различия:

  • Мы отправляем два значения в execute() функция: Строка запроса с вопросительными знаками (заполнителями) и значениями, которые должны использоваться для этих заполнителей (все предыдущие методы отправляли только одно значение: строку SQL, которую мы вручную создали со значениями).
  • Мы не заменяем знаки вопроса сами. Мы разрешаем библиотеке БД разобраться с этим
  • Нам не нужно беспокоиться о цитировании (обратите внимание, что вокруг вопросительных знаков нет кавычек).

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

Разрешение библиотеке БД работать с заполнителями позволяет БД решать, как правильно заключать в кавычки значения, что уменьшает вышеупомянутую атаку SQL-Injection.

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