SQLite3 和 Python 3 - "no such column" 字符串错误而不是整数

SQLite3 and Python 3 - "no such column" error with strings but not integers

对于这个项目,我有一个数据库文件,其中 table 结果如下所示:

conn.execute('''CREATE TABLE RESULTS(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age TEXT NOT NULL,
gender TEXT NOT NULL);''')

这是我用来创建原型前端的文件,以便用户可以访问数据库中的数据:

#setting up the user input variables
srcIn = input("what field do you want to search: id, name, age, or gender? ")
srcQuery = input("what result do you want to find from the "+ srcIn + " search? ")
if(srcIn == "age") or (srcIn == "id"):
    #by default input returns a string but it needs to be an int for age and id parameters
    srcQuery = int(srcQuery)
    print("converted to int")
srcOut = input("what field do you want to return: id, name, age, or gender? ")

print("making cursor")
cursor = conn.execute("SELECT %s FROM RESULTS WHERE %s = %s" % (srcOut, srcIn, srcQuery))
for row in cursor:
    print(srcOut + ": " + row[0])

conn.close()
print("closed database " + db)

如果我要 运行 这个并传递给它年龄或 ID,数字 45,并给它命名,我的数据库中的名字、性别和其他统计数据将 return 完美。但是,当我传递性别、女性或男性,并 return 输入姓名、年龄或 ID 时,会弹出一条错误消息:

cursor = conn.execute("SELECT %s FROM RESULTS WHERE %s = %s" % (srcOut, srcIn, srcQuery))
sqlite3.OperationalError: no such column: male

对于这个具体的例子:

srcOut = name
srcIn = gender
srcQuery = male

我试过将 %s 替换为 ?参数(我知道它不会对我传递给 SELECT 语句的参数起作用),所以我很困惑。

我认为这与以下事实有关:在某些情况下,我在 srcQuery 字段中向它传递一个整数,而在其他情况下,我向它传递一个字符串。

如有任何帮助或建议,我们将不胜感激。

不,你不应该按照@Suever 建议的方式去做

想象一下,如果我提供以下值,将会执行什么查询:

srcOut = "name"
srcIn = "gender"
srcQuery = "' or 1 = 1 -- "

您的代码将实际执行:

SELECT 
    name 
FROM 
    RESULTS 
WHERE  
    gender = '' or 1 = 1 -- '

这将匹配 table 中的每一行。

或者,换句话说,由于缺乏任何验证和转义,并且通过准备特定的输入,我得到了 table 中的所有结果,这当然是你不知道的不想发生在现实世界中。这称为 SQL injection attack.

您应该参数化您的查询,而不是字符串格式化。 Query parameterization though is not going to work for table and column names - 这些你需要在插入查询之前验证 - 因为 scrInsrcOut 的可能值的数量非常有限 - 如果你看到意外值,例如:

columns = {'id', 'name', 'age', 'gender'} 
srcIn = input("what field do you want to search: id, name, age, or gender? ")
if srcIn not in columns:
    raise ValueError("Invalid srcIn value")

至于 srcQuery - 这个你需要 参数化 :

query = "SELECT {column_out} FROM RESULTS WHERE {column_in} = ?".format(column_out=srcOut, column_in=scrIn)
cursor = conn.execute(query, (srcQuery, ))

除了更安全之外,这还将消除考虑 python 到数据库类型转换和引号的问题 - 数据库驱动程序会自动处理。