Возникли проблемы при обновлении таблицы базы данных со строками sqlite3 - PullRequest
0 голосов
/ 26 мая 2018

У меня проблема с python, sqlite3, где я могу обновить таблицу с числами (int или decimal), но без строк. ссылка на снимок экрана с запущенной здесь программой

def amendRec():    #FIX ME PLEASE
edit="yes"
while edit !='exit':
    keyfield=input("enter the game name of the record you want to edit. ")
    keyfield="'"+keyfield+"'"
    field=input("enter the field you want to change. ")

    newVal=input("enter the new data for this field. ")
    #try:
    cursor.execute("UPDATE tblGames SET " + field + "=" + newVal +  " WHERE game = " + keyfield)
    conn.commit()
    print("\nRecord Updated\n")
    #except:
        #print("invalid game name or field entered.")
    edit=input("type 'exit' to stop editing, or press enter to continue. \n")
    showtable()

Оператор исключения закомментирован, поэтому я вижу сообщение об ошибке для оператора try.Опять же, он отлично работает, когда я пытаюсь обновить запись в число, но когда я пытаюсь обновить строку, он выдает сообщение об ошибке:

Traceback (последний вызов был последним): File«C: / Users / 12smi / Documents / school / computing / SQL / база данных с добавлением и удалением function.py», строка 99, в файлеmendRec () «C: / Users / 12smi / Documents / school / computing / SQL /база данных с добавлением и удалением function.py ", строка 82, вmendRec cursor.execute (" ОБНОВЛЕНИЕ tblGames SET "+ поле +" = "+ newVal +" WHERE game = "+ ключевое поле) sqlite3.OperationalError: нет такого столбца: Приключение

(«Приключение» - это строка, которую я ввел в это время)

Я понятия не имею, почему это происходит, поэтому любая помощь будет отличной :)

1 Ответ

0 голосов
/ 27 мая 2018

Вы получаете эту ошибку, потому что вы пытались выполнить

UPDATE tblGames SET genre=Adventure WHERE game = 'Shadow of the Colossus';

, в то время как вы, вероятно, намеревались выполнить

UPDATE tblGames SET genre='Adventure' WHERE game = 'Shadow of the Colossus';

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

В вашем коде есть большая проблема, на которую уже указали комментарии.Вы объединяете ваш запрос, используя неанализованные строки, которые являются антипаттернами.Библиотека sqlite3 Python позволяет вам связывать параметры с вашими запросами.Любой ? в вашем запросе будет заменен значением по вашему выбору (пример ниже).

Однако у вас есть другая проблема.Вы не можете связать имя столбца как параметр.Попытка сделать это будет иметь 'columnName' в запросе вместо columnName.Там нет безопасного способа сделать это, потому что это еще один антипаттерн.Но так как мы здесь, давайте по крайней мере сделаем это безопасным способом.Нам придется встраивать имя столбца в запрос, но мы не можем встроить какой-либо пользовательский ввод, опасаясь внедрения SQL.Поэтому мы должны убедиться, что встраиваемая строка является именем столбца и только именем столбца.Другими словами, нам нужно будет санировать входные данные.

Приведенный ниже код будет санировать имя столбца, так что в запрос попадут только действительные имена столбцов.Он также встраивает другие параметры, используя функциональность sqlite3, которая очищает входные данные для вас.

def amendRec():
    edit = "yes"
    while edit != 'exit':
        keyfield = input("enter the game name of the record you want to edit. ")
        field = input("enter the field you want to change. ")

        # Check whether the specified colmun exists or not.
        # Any SQL injection will fail this test.
        query = "PRAGMA table_info ('tblGames');"
        columnExists = False
        for columnName in map(lambda x: x[1], cur.execute(query)):
            if columnName == field:
                columnExists = True

        if columnExists:
            # field can only be one of the column names since it's sanitized above.
            query = "UPDATE tblGames SET {} = ? WHERE game = ? ;".format(field)
            new_val = input("enter the new data for this field. ")
            # We pass in a tuple containing our desired parameters as the second parameter of cursor.execute.
            # new_val will replace the first ? and keyfield will replace the second ?.
            cursor.execute(query, (new_val, keyfield))
            conn.commit()
            print("\nRecord Updated\n")
        else:
            print("Sorry, that column doesn't exist.")

        edit = input("type 'exit' to stop editing, or press enter to continue. \n")
        showtable()

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

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