Python, MySQLdb y nombres de tablas de escape?

Puede que me esté faltando algo obvio, pero no puedo entender en qué se diferencia mi código de varios ejemplos que veo en la documentación en línea para MySQLdb.

Soy bastante nuevo en la progtwigción de python, más experimentado con perl. Lo que estoy tratando de hacer es adentrarme en ciertos buenos hábitos desde el principio (como en perl, siempre comienzo con ‘uso estricto; uso de advertencias’), por lo que estoy tratando de asegurar que cree funciones reutilizables en un archivo independiente ( funct.py) para ahorrar tiempo más adelante en la línea.

Tengo esta función para seleccionar filas aleatorias de una tabla:

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] 

Se llama así:

 msg = funct.returnRandom(conn,"id","testtable","data") 

Desafortunadamente, se produce un error con: _mysql_exceptions.ProgrammingError: (1064, “Tiene un error en su syntax SQL; consulte el manual que corresponde a la versión de su servidor MySQL para obtener la syntax correcta para usar cerca de ” testtable ” en la línea 1″)

Si pongo la tabla de prueba en lugar de% s en la línea de ejecución, la consulta se ejecutará pero parece que se ejecuta

 SELECT MAX('id') FROM testtable; 

que por supuesto devuelve ‘id’.

Dados los dos, parece que está citando las entradas% s cuando intenta ejecutarlas. Me preguntaba si alguien podría explicar cómo puedo dejar de hacer eso, o cómo debería estar haciendo lo que estoy tratando de lograr. Quiero que la función sea lo más genérica posible, por lo que depender de los datos que se le pasan cuando se llama.

Edición: Debería agregar, si sustituyo en? marcas:

 .... 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 

No puede utilizar DB-API para metadatos; Necesitará hacer reemplazos usted mismo fuera de la llamada a execute() .

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

Obviamente, no debes hacer esto si la table proviene de una fuente externa.

MySQLdb probablemente está citando los nombres de sus tablas con comillas simples en lugar de comillas invertidas. Prueba esto

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

Interesante. Pero en el manual hay un par de ejemplos. Tal vez sea algo similar.

 c=db.cursor() max_price=5 c.execute("""SELECT spam, eggs, sausage FROM breakfast WHERE price < %s""", (max_price,)) 

En este ejemplo, max_price = 5 ¿Por qué, entonces, usa% s en la cadena? Porque MySQLdb lo convertirá a un valor literal de SQL, que es la cadena '5'. Cuando termine, la consulta dirá: "... DONDE el precio <5".

Y

 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 ) ] ) 

Aquí estamos insertando tres filas de cinco valores. Tenga en cuenta que hay una mezcla de tipos (cadenas, ints, flotadores) aunque todavía solo usamos% s. Y también tenga en cuenta que solo incluimos cadenas de formato para una fila. MySQLdb los selecciona y los duplica para cada fila.