2010-06-28 146 views
19

Me está costando conseguir algunos sql en python para pasar MySQLdb correctamente. Es el formato de cadenas de pitones que me está matando.Formatos de cadena de Python con comodines SQL y LIKE

Mi declaración sql usa la palabra clave LIKE con comodines. He intentado varias cosas diferentes en Python. El problema es que una vez que uno de ellos funciona, hay una línea de código en MySQLdb que eructa en formato de cadena.

Intento 1:

"SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN tag ON user.id = tag.userId WHERE user.username LIKE '%%s%'" % (query)

Esto es un no ir. Llego valor de error:

ValueError: unsupported format character ''' (0x27) at index 128

Intento 2:

"SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN tag ON user.id = tag.userId WHERE user.username LIKE '\%%s\%'" % (query)

puedo obtener el mismo resultado del intento 1.

Intento 3:

like = "LIKE '%" + str(query) + "%'" totalq = "SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN tag ON user.id = tag.userId WHERE user.username " + like

Esto crea correctamente el totalq variable, pero ahora cuando voy a ejecutar la consulta obtengo errores de MySQLdb:

File "build/bdist.macosx-10.6-universal/egg/MySQLdb/cursors.py", line 158, in execute query = query % db.literal(args) TypeError: not enough arguments for format string

Intento 4:

like = "LIKE '\%" + str(query) + "\%'" totalq = "SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN tag ON user.id = tag.userId WHERE user.username " + like

Este es el mismo resultado que el intento 3.

Todo esto parece muy extraño. ¿Cómo puedo usar comodines en sentencias sql con python?

+0

Para eco @bernie a continuación: De docs psycopg: http://initd.org/psycopg/docs/usage.html#the-problem-with-the-query-parameters: "Nunca, nunca, nunca usar Python concatenación de cadenas (+) o interpolación de parámetros de cadena (%) para pasar variables a una cadena de consulta SQL. . Ni siquiera a punta de pistola "Además de los ataques de inyección SQL, un segundo beneficio es que el conductor 'puede convertir automáticamente los objetos de Python desde y hacia los literales SQL: el uso de esta función, su código será más robusto y fiable un ingenuo' Este frente." enfoque a la composición de cadenas de consulta, por ejemplo .. El uso de la concatenación de cadenas" –

Respuesta

10

No se trata de formato de cadenas, pero el problema es cómo las consultas deben ser ejecutados de acuerdo a los requerimientos db operaciones en Python (PEP 249)

intentar algo como esto:

sql = "SELECT column FROM table WHERE col1=%s AND col2=%s" 
params = (col1_value, col2_value) 
cursor.execute(sql, params) 

here are some examples for psycog2 donde tiene algunas explicaciones eso también debería ser válido para mysql (mysqldb también sigue PEP249 dba api guidance 2.0: here are examples for mysqldb)

+0

Gracias. que lo hizo. por alguna razón, pensé MySQL db sería encontrar la manera de escapar de los parámetros incluso en el interior de la instrucción SQL. Pero ahora que tiene sentido tirar parámetros de esta manera. – gngrwzrd

+0

Estamos encantados de que te ayudó! pasé mucho tiempo hasta que me di que hace un tiempo :) – dzida

6

Para escapar de los símbolos de unión en Python expresiones de cadenas, el doble del signo:

'%%%s%%' % search_string 

Editar: Pero estoy totalmente de acuerdo con otra respuesta. La sustitución directa de cadenas en consultas SQL casi siempre es una mala idea.

20

Esas consultas parecen ser vulnerables a los ataques de inyección de SQL.

intentar algo como esto en su lugar:

curs.execute("""SELECT tag.userId, count(user.id) as totalRows 
        FROM user 
      INNER JOIN tag ON user.id = tag.userId 
       WHERE user.username LIKE %s""", ('%' + query + '%',)) 

Donde hay dos argumentos que se pasa a execute().

+1

Eso también se ve vulnerable a la inyección SQL mediante consultas con parámetros a través de cualquier biblioteca se utiliza para conectarse a la base de datos es el camino a seguir – jrdioko

+4

@jrdioko:.. Gracias por su comentario Tenga en cuenta que no hay ninguna interpolación cadena real y que la consulta * se * preparado por el 'execute()' método. – bernie

+0

lo dicho, parece que la sintaxis es la forma en la biblioteca en cuestión no consultas con parámetros. – jrdioko

-1

tengo una solución a su problema:

No se puede utilizar:

"SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN tag ON user.id = tag.userId WHERE user.username LIKE '%%s%'" % (query) 

puede cambiar con plantilla de cadena, tales como:

import MySQLdb 
import string # string module 
....... 
value = {'user':'your value'} 
sql_template = string.Template(""" 
SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN 
tag ON user.id = tag.userId WHERE user.username LIKE '%$user%' 
""") 

sql = sql_template.substitute(value) 

try: 
    cursor.execute(sql) 
    ........... 
except: 
    ........... 
finally : 
    db.close() 
+0

este no es mejor que la sustitución directa que no se debe hacer de todos modos. los marcadores de posición como se describe arriba y en el PEP 249 doc describir cómo hacer esto correctamente – Turk

Cuestiones relacionadas