Python、MySQLdb和转义表名?

Python、MySQLdb和转义表名?,python,mysql-python,Python,Mysql Python,我可能遗漏了一些明显的东西,但我无法理解我的代码与我在MySQLdb在线文档中看到的各种示例有何不同 我对python编程相当陌生,对perl有更多的经验。我试图做的是在早期养成一些好习惯(比如在perl中,我总是从“使用严格;使用警告”开始),因此我试图确保在独立文件(funct.py)中创建可重用的函数,以节省以后的时间 我有一个从表中选择随机行的函数: def returnRandom(conn,countcol,table,field): cursor = conn.cursor

我可能遗漏了一些明显的东西,但我无法理解我的代码与我在MySQLdb在线文档中看到的各种示例有何不同

我对python编程相当陌生,对perl有更多的经验。我试图做的是在早期养成一些好习惯(比如在perl中,我总是从“使用严格;使用警告”开始),因此我试图确保在独立文件(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

元数据不能使用DB-API;您需要自己在
execute()
调用之外进行替换

query = 'SELECT MAX(%%s) FROM `%s`' % (table,)
cursor.execute(query, (countcol,))

显然,如果
table
来自外部源,您不应该这样做。

MySQLdb可能用单引号而不是反勾号引用您的表名。试试这个

cursor.execute('SELECT MAX(%%s) FROM `%s`' % table,(countcol))
有趣。但是,在本文中有几个例子。也许是类似的

c=db.cursor()
max_price=5
c.execute("""SELECT spam, eggs, sausage FROM breakfast
          WHERE price < %s""", (max_price,))
这里我们插入三行五个值。注意,有 类型(字符串、整数、浮点)的混合,尽管我们仍然只使用%s。 还要注意,我们只为一行包含格式字符串。 MySQLdb会将它们挑选出来,并为每一行复制它们


这正是我想要避免的。我已经使用format函数实现了类似的功能,但我想做得更安全一点。不,这也失败了,现在仍在寻找数据库“table”!这个答案与@Ignacio的答案基本相同。我不知道你最后怎么会被引用。是否在带引号的字符串末尾键入了反勾号
%s
?问题是转义表名,而不是列值。
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 )
      ] )