无法使用字符串更新数据库表sqlite3

时间:2018-05-26 14:14:46

标签: python sqlite

我遇到python,sqlite3的问题,我可以使用数字(int或decimal)更新表,但不能更新字符串。 link to a screenshot of program running here

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()

except语句被注释掉,所以我可以看到try语句的错误消息。同样,当我尝试将enrty更新为数字时它完美地工作,但是当我尝试更新为字符串时,它会给出错误消息:

  

追踪(最近一次通话):     文件“C:/ Users / 12smi / Documents / school / computing / SQL / database with add and remove function.py”,第99行,in       amendRec()     文件“C:/ Users / 12smi / Documents / school / computing / SQL / database with add and remove function.py”,第82行,在revisionRec中       cursor.execute(“UPDATE tblGames SET”+ field +“=”+ newVal +“WHERE game =”+ keyfield)   sqlite3.OperationalError:没有这样的列:冒险

('冒险'是我输入那个时间的字符串)

我不知道为什么会这样,所以任何帮助都会很棒:)

1 个答案:

答案 0 :(得分:0)

您因为尝试执行

而收到该错误
UPDATE tblGames SET genre=Adventure WHERE game = 'Shadow of the Colossus';

虽然你可以执行

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

如果你只是去做那个改变它会起作用,但我会和你交叉,因为你的代码危险

您的代码中存在更大的问题,评论已经指出。您正在使用未经规范化的字符串拼接您的查询,这是一个反模式。 Python的sqlite3库允许您将参数绑定到查询中。查询中的任何?都将替换为您选择的值(例如下面的内容)。

但是你有另一个问题。您不能将列名绑定为参数。尝试这样做会在查询中使用'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是一个多选输入而不是文本输入。通过这种方式,您可以更加确定它是安全的,并且您必须减少对数据库的查询。