[英]Python Sqlite3 - Using f strings for update database function
I have my own personal database I made for fun (so not that concerned with sql injections as its my own private database I made) and am trying to change the functions I created that use string formatting (.format()) and placeholders (?, %s, etc) and use f strings instead.我有我自己的个人数据库,我为了好玩(所以不关心 sql 注入,因为它是我自己制作的私人数据库),并试图更改我创建的使用字符串格式 (.format()) 和占位符 (? 、%s 等)并使用 f 字符串代替。 I ran into a problem where one of my functions that updates a specified column into a specified row won't run now that I changed the sqlite3 query to f strings.我遇到了一个问题,因为我将 sqlite3 查询更改为 f 字符串后,我的一个将指定列更新为指定行的函数将无法运行。
This is my current function using f strings:这是我当前使用 f 字符串的函数:
import sqlite3
from tabulate import tabulate
conn = sqlite3.connect("Table.db")
c = conn.cursor()
def updatedb(Column, Info, IdNum):
with conn:
data = c.execute(f"UPDATE Table_name SET {Column} = {Info} WHERE IdNum={IdNum}")
c.execute(f"SELECT * FROM Table_name WHERE IdNum = {IdNum}")
print(tabulate(data, headers="keys", tablefmt="grid", stralign='center', numalign='center'))
The function updates the table by updating a specified column of a specified row with the new info you want in that column.该函数通过使用您想要的列中的新信息更新指定行的指定列来更新表。 For example in a 3 x 3 table, instead of row 1, column 2 being 17, I can use the function to update row 1, column 2 to 18 if that column is an age or something.例如,在 3 x 3 表中,如果该列是年龄或其他内容,我可以使用该函数将第 1 行第 2 列更新为 18,而不是第 1 行第 2 列。 The select query after that is to just select that particular row that was updated and the print statement after that uses the tabulate package to print out a neat and organized table.之后的选择查询只是选择更新的特定行,之后的打印语句使用 tabulate 包打印出一个整洁有序的表格。
The error I get whenever I try to use this function is:每当我尝试使用此功能时出现的错误是:
sqlite3.OperationalError: no such column: Info
Whatever I type in for the Info variable in the function is what the error becomes but I can't figure out how to fix the problem.无论我在函数中为 Info 变量输入什么,都会导致错误,但我不知道如何解决这个问题。
This is the update statement I had before attempting to change to f strings and it worked fine for me:这是我尝试更改为 f 字符串之前的更新语句,它对我来说很好用:
data = c.execute("UPDATE Table_name SET {} = ? WHERE IdNum=?".format(Column), (Info, IdNum))
It didn't seem like to would be that big of a change to change the above query to af string but it isn't working so any feedback would be appreciated.将上述查询更改为 af 字符串似乎没有那么大的变化,但它不起作用,因此将不胜感激任何反馈。
The problem here is understanding parameterization - it works only for parameters, not for column names and other stuff.这里的问题是理解参数化 - 它仅适用于参数,不适用于列名和其他内容。
in this example:在这个例子中:
query = 'SELECT * FROM foo WHERE bar = ? AND baz = ?'
params = (a, b)
cursor.execute(query, params)
Note that the query and the data are passed separately to .execute
- it is the database's job to do the interpolation - that frees you from quote hell, and makes your program safer by disabling any kind of sql injection.请注意,查询和数据分别传递给.execute
-它是数据库的工作做插值-从报价地狱的FreeS你,使你的程序通过禁用任何类型的SQL注入安全。 It also could perform better - it allows the database to cache the compiled query and use it when you change parameters.它也可以表现得更好——它允许数据库缓存编译后的查询并在您更改参数时使用它。
Now that only works for data .现在这只适用于data 。 If you want to have the actual column name in a variable, you have to interpolate it yourself in the query:如果你想在一个变量中有实际的列名,你必须自己在查询中插入它:
col1 = 'bar'
col2 = 'baz'
query = f'SELECT * FROM foo WHERE {col1} = ? AND {col2} = ?'
cursor.execute(query, params)
Parameterization and string substitution are two very different things.参数化和字符串替换是两件非常不同的事情。
At the most basic level, your problem is that string substitution is producing a command of the form:在最基本的层面上,您的问题是字符串替换正在生成以下形式的命令:
. . . SET some_column = some_info . . .
where SQL requires SQL 需要的地方
. . . SET some_column = 'some_info' . . .
(that is, quotes around the string value). (即,字符串值周围的引号)。 SQLite is interpreting the the unquoted string as an expression consisting of a column name. SQLite 将未加引号的字符串解释为由列名组成的表达式。
You cannot solve this problem by simply adding single quotes into your format string as you may believe.正如您所相信的那样,您无法通过简单地在格式字符串中添加单引号来解决此问题。 What happens if the substituted value itself contains a single quote?如果替换值本身包含单引号会发生什么? This way lies both string-escaping madness and the danger of SQL injection.这种方式既有疯狂的字符串转义,也有 SQL 注入的危险。
Instead, just use parameterization.相反,只需使用参数化。
But, note that you can't parameterize the column name ( {Column}
), you would have to use string substitution for that while taking care not to allow injection to occur.但是,请注意,您不能参数化列名 ( {Column}
),您必须为此使用字符串替换,同时注意不允许发生注入。
To improve upon nosklo 's answer above concerning the use of f-strings , you just have to use escaped quotes around the variables so they are sent as a string to SQLite:为了改进上面关于f-strings使用的nosklo的答案,您只需要在变量周围使用转义引号,以便将它们作为字符串发送到 SQLite:
import sqlite3
conn = sqlite3.connect("somedatabase.db")
c = conn.cursor()
def updatedb(colname, colvalue, rowid):
with conn:
c.execute(f"UPDATE tablename SET \"{colname}\" = \"{colvalue}\" WHERE rowidentifier = \"{rowid}\"")
For safety reasons, don't use string interpolation with a database that relies on external user input.出于安全原因,不要对依赖外部用户输入的数据库使用字符串插值。 But, if you sanitize the input string(s), I guess you can make it work.但是,如果您清理输入字符串,我想您可以使它工作。
i am using mysql.connector我正在使用mysql.connector
query = "INSERT INTO PICS (name,image) VALUES (%s,%s)"
param = (fname, DATA)
cursor.execute(query, param)
print("DONEEEEEE" * 100)
conn.commit()
cursor.close()
conn.close()
this is for the latest version of '8.0.27' for 2021这是 2021 年最新版本的“8.0.27”
this worked for me !!!!这对我有用!!!!
I have my own personal database I made for fun (so not that concerned with sql injections as its my own private database I made) and am trying to change the functions I created that use string formatting (.format()) and placeholders (?, %s, etc) and use f strings instead.我有我自己的个人数据库,我为了好玩(所以不关心 sql 注入,因为它是我自己创建的私有数据库),并且正在尝试更改我创建的使用字符串格式 (.format()) 和占位符 (? 、%s 等)并使用 f 字符串代替。 I ran into a problem where one of my functions that updates a specified column into a specified row won't run now that I changed the sqlite3 query to f strings.我遇到了一个问题,因为我将 sqlite3 查询更改为 f 字符串后,我的一个将指定列更新为指定行的函数将无法运行。
This is my current function using f strings:这是我当前使用 f 字符串的函数:
import sqlite3
from tabulate import tabulate
conn = sqlite3.connect("Table.db")
c = conn.cursor()
def updatedb(Column, Info, IdNum):
with conn:
data = c.execute(f"UPDATE Table_name SET {Column} = {Info} WHERE IdNum={IdNum}")
c.execute(f"SELECT * FROM Table_name WHERE IdNum = {IdNum}")
print(tabulate(data, headers="keys", tablefmt="grid", stralign='center', numalign='center'))
The function updates the table by updating a specified column of a specified row with the new info you want in that column.该函数通过使用您想要的列中的新信息更新指定行的指定列来更新表。 For example in a 3 x 3 table, instead of row 1, column 2 being 17, I can use the function to update row 1, column 2 to 18 if that column is an age or something.例如,在 3 x 3 表中,如果该列是年龄或其他内容,我可以使用该函数将第 1 行第 2 列更新为第 18 行,而不是第 1 行第 2 列。 The select query after that is to just select that particular row that was updated and the print statement after that uses the tabulate package to print out a neat and organized table.之后的选择查询只是选择更新的特定行,之后的打印语句使用 tabulate 包打印出一个整洁有序的表格。
The error I get whenever I try to use this function is:每当我尝试使用此功能时出现的错误是:
sqlite3.OperationalError: no such column: Info
Whatever I type in for the Info variable in the function is what the error becomes but I can't figure out how to fix the problem.无论我在函数中为 Info 变量输入什么,都会导致错误,但我不知道如何解决这个问题。
This is the update statement I had before attempting to change to f strings and it worked fine for me:这是我尝试更改为 f 字符串之前的更新语句,它对我来说很好用:
data = c.execute("UPDATE Table_name SET {} = ? WHERE IdNum=?".format(Column), (Info, IdNum))
It didn't seem like to would be that big of a change to change the above query to af string but it isn't working so any feedback would be appreciated.将上述查询更改为 af 字符串似乎没有那么大的变化,但它不起作用,因此将不胜感激任何反馈。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.