Python、MySQLdb及转义表名?
我可能漏掉了什么明显的东西,但我就是搞不清楚我的代码和我在MySQLdb的在线文档中看到的各种例子有什么不同。
我对Python编程还比较陌生,更熟悉Perl。我想尽早养成一些好的习惯(就像在Perl中我总是从'use strict; use warnings'开始),所以我想确保我在一个独立的文件中创建可重用的函数(funct.py),这样以后可以节省时间。
我有一个从表中选择随机行的函数:
def returnRandom(conn,countcol,table,field):
cursor = conn.cursor()
cursor.execute('SELECT MAX(%s) FROM %s',(countcol,table))
maxRow = cursor.fetchone()[0]
cursor.execute("SELECT MIN(%s) FROM %s",(countcol,table))
minRow = cursor.fetchone()[0]
randomId = random.randrange(minRow,maxRow+1,1)
cursor.execute("SELECT ? FROM ? WHERE id >=? LIMIT 1",field,table,randomId)
return cursor.fetchone()[0]
它是这样被调用的:
msg = funct.returnRandom(conn,"id","testtable","data")
不幸的是,它出现了错误:
_mysql_exceptions.ProgrammingError: (1064, "你的SQL语法有错误;请检查与您的MySQL服务器版本相对应的手册,以获取在第1行使用的正确语法,靠近'testtable'")如果我在执行行中把testtable直接放在%s的位置,查询会运行,但看起来它执行的是
SELECT MAX('id') FROM testtable;
这当然会返回'id'。
根据这两点来看,似乎在执行时它把%s的内容加了引号。我想知道有没有人能解释一下我该如何让它停止这样做,或者我应该如何实际实现我想要的功能?我希望这个函数尽可能通用,所以希望在调用时传入数据。
补充:我应该补充一下,如果我用问号替代:
....
cursor.execute('SELECT MAX(?) FROM ?',(countcol,table))
File "/usr/lib/pymodules/python2.7/MySQLdb/cursors.py", line 151, in execute
query = query % db.literal(args)
TypeError: not all arguments converted during string formatting
3 个回答
-1
有趣。不过在手册里有几个例子。也许这和你说的有点像。
c=db.cursor()
max_price=5
c.execute("""SELECT spam, eggs, sausage FROM breakfast
WHERE price < %s""", (max_price,))
在这个例子中,max_price=5。那么,为什么在字符串中使用 %s 呢?因为 MySQLdb 会把它转换成一个 SQL 字面值,也就是字符串 '5'。等它完成后,查询实际上会变成 "...WHERE price < 5"。
还有
c.executemany(
"""INSERT INTO breakfast (name, spam, eggs, sausage, price)
VALUES (%s, %s, %s, %s, %s)""",
[
("Spam and Sausage Lover's Plate", 5, 1, 8, 7.95 ),
("Not So Much Spam Plate", 3, 2, 0, 3.95 ),
("Don't Wany ANY SPAM! Plate", 0, 4, 3, 5.95 )
] )
这里我们插入了三行,每行五个值。注意,这里有不同类型的数据(字符串、整数、浮点数),但我们仍然只使用 %s。还要注意,我们只为一行提供了格式字符串。MySQLdb 会把这些格式字符串提取出来,并为每一行复制一份。
0
MySQLdb 可能用单引号把你的表名括起来,而不是用反引号。你可以试试这个
cursor.execute('SELECT MAX(%%s) FROM `%s`' % table,(countcol))
3
你不能用数据库接口(DB-API)来处理元数据;你需要在调用execute()
之前自己进行替换。
query = 'SELECT MAX(%%s) FROM `%s`' % (table,)
cursor.execute(query, (countcol,))
显然,如果table
是来自外部来源的话,你就不应该这样做。