使用Python通过变量列名访问SQL
我想用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驱动程序在处理这个变量时会尝试对它进行转义,包括加上引号,而这对于列名、表名等来说并不是你想要的。
在使用SELECT
、WHERE
等语句时,如果是用到值,那么你确实应该使用%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提到的那样,有任何外部输入,那就完全不同了,需要采取额外的预防措施。