使用Python通过变量列名访问SQL

1 投票
1 回答
5288 浏览
提问于 2025-04-18 13:20

我想用pymysql把我的代码连接到MySQL数据库。总体来说,一切都很顺利,但我在一个函数上遇到了一些困难,这个函数是用来找出某个变量列的最小值。

def findmin(column):
    cur = db.cursor()
    sql = "SELECT MIN(%s) FROM table"
    cur.execute(sql,column)
    mintup = cur.fetchone()

如果一切正常,这个函数应该会返回一个包含最小值的元组,比如说(1,)

但是,当我运行这个函数时:

findmin(column_name)

我必须把列名放在""里(也就是"column_name"),否则Python会把它当成一个未知的变量。但如果我把引号加在column_name周围,SQL就会看到

SELECT MIN("column_name") FROM table

这只会返回列的标题,而不是实际的值。

我该怎么解决这个问题呢?

1 个回答

2

这个问题可能是因为使用了%s来表示列名。这样的话,SQL驱动程序在处理这个变量时会尝试对它进行转义,包括加上引号,而这对于列名、表名等来说并不是你想要的。

在使用SELECTWHERE等语句时,如果是用到,那么你确实应该使用%s,这样可以防止SQL注入,并且可以进行引号处理等。

在这里,你只想用纯Python来处理(假设这个值是可信的;更多信息请见下文)。这也意味着在调用execute方法时不需要传递绑定元组。

def findmin(column):
    cur = db.cursor()
    sql = "SELECT MIN({0}) FROM table".format(column)
    cur.execute(sql)
    mintup = cur.fetchone()

这是一个展示SQL正常工作的示例:

http://sqlfiddle.com/#!2/e70a41/1

关于Colin Phipps在2014年7月15日的评论(2022年9月):

最近另一位社区成员对这篇帖子进行了编辑,引起了我的注意,我想回应Colin多年前的评论。

我完全同意在像这样进行插值时要小心输入。确实需要准确知道插入的内容是什么。在这种情况下,我认为在可信的内部脚本中定义的值,或者由可信的内部来源提供的值是可以的。但是如果像Colin提到的那样,有任何外部输入,那就完全不同了,需要采取额外的预防措施。

撰写回答