python - 使用字符串 sqlite3 更新数据库表时遇到问题
问题描述
python, sqlite3 有问题,我可以用数字(整数或十进制)而不是字符串更新表。 链接到此处运行的程序的屏幕截图
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 行,在 amendRec() 文件“C:/Users/12smi /Documents/school/computing/SQL/database with add and remove function.py”,第 82 行,在 amendRec cursor.execute("UPDATE tblGames SET" + field + "=" + newVal +" WHERE game = " + keyfield) sqlite3.OperationalError:没有这样的列:冒险
('Adventure'是我当时输入的字符串)
我不知道为什么会发生这种情况,所以任何帮助都会很棒:)
解决方案
您收到该错误是因为您尝试执行
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
应该是多选输入而不是文本输入。这样您就可以更加确定它是安全的,并且您必须少对数据库进行一次查询。
推荐阅读
- r - Lapply 使用另一个列表作为标准过滤一个列表的值
- javascript - 如何将图像保存到 discord.js 中的文件
- java - 信号量是否可以在数据结构对象中声明和使用(例如,一个自我实现的队列)
- python - 如何从 html 模板中的 jinja2 循环请求.form
- xtext - Code Composer Studio Eclipse 环境中缺少什么?
- javascript - Javascript Web 应用程序测试
- python - 如何在 TensorFlow 中为矢量化参数设置双射器?
- ios - AVCapture 似乎滞后,文本识别不会立即开始
- json - 从 JSON 数组中获取名称并在 Listview 中显示第一个字符
- clang - Clang AST Interpretation