使用字符串更新数据库表sqlite3时遇到问题

2024-06-16 21:39:47 发布

您现在位置:Python中文网/ 问答频道 /正文

我对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更新为一个数字时,它可以很好地工作,但是当我尝试更新为一个字符串时,它会给出错误消息:

Traceback (most recent call last): File "C:/Users/12smi/Documents/school/computing/SQL/database with add and remove function.py", line 99, in amendRec() File "C:/Users/12smi/Documents/school/computing/SQL/database with add and remove function.py", line 82, in amendRec cursor.execute("UPDATE tblGames SET " + field + "=" + newVal + " WHERE game = " + keyfield) sqlite3.OperationalError: no such column: Adventure

('Adventure'是我当时输入的字符串)

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


Tags: oftheto字符串gamefieldinputexit
1条回答
网友
1楼 · 发布于 2024-06-16 21:39:47

你得到那个错误是因为你试图执行

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应该是多选输入,而不是文本输入。这样,您就可以更加确定它的安全性,并且只需对数据库进行一次查询

相关问题 更多 >