我遇到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:没有这样的列:冒险
('冒险'是我输入那个时间的字符串)
我不知道为什么会这样,所以任何帮助都会很棒:)
答案 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
是一个多选输入而不是文本输入。通过这种方式,您可以更加确定它是安全的,并且您必须减少对数据库的查询。