query examples datos consultar conectar con python sql django psycopg2

examples - Cómo citar explícitamente un valor de cadena(Python DB API/Psycopg2)



psycopg2 insert (9)

Por alguna razón, me gustaría hacer una cita explícita de un valor de cadena (convirtiéndose en una parte de la consulta SQL construida) en lugar de esperar la cita implícita realizada por el método cursor.execute en los contenidos de su segundo parámetro.

Por "cita implícita" quiero decir:

value = "Unsafe string" query = "SELECT * FROM some_table WHERE some_char_field = %s;" cursor.execute( query, (value,) ) # value will be correctly quoted

Yo preferiría algo como eso:

value = "Unsafe string" query = "SELECT * FROM some_table WHERE some_char_field = %s;" % / READY_TO_USE_QUOTING_FUNCTION(value) cursor.execute( query ) # value will be correctly quoted, too

Es ese nivel bajo READY_TO_USE_QUOTING_FUNCTION esperado por la especificación Python DB API (no pude encontrar tal funcionalidad en el documento PEP 249 ). Si no, ¿tal vez Psycopg2 proporciona esa función? Si no, ¿tal vez Django proporciona esa función? Preferiría no escribir esa función yo mismo ...


Esto dependerá de la base de datos (iirc, mysql permite / como un carácter de escape, mientras que algo como oracle espera que las comillas se dupliquen: ''my '''' quoted string'' ).

Alguien me corrige si estoy equivocado, pero el método de doble cita es el método estándar.

Puede valer la pena ver qué hacen otras bibliotecas de abstracción de db (sqlalchemy, cx_Oracle, sqlite, etc.).

Tengo que preguntar: ¿por qué quieres alinear los valores en lugar de vincularlos?


Esto va a depender de DB. En el caso de MySQLdb, por ejemplo, la clase de connection tiene un método literal que convertirá el valor a la representación escapada correcta para pasar a MySQL (eso es lo que usa cursor.execute ).

Me imagino que Postgres tiene algo similar, pero no creo que exista una función para escapar de los valores como parte de la especificación DB API 2.0.


Debería tratar de evitar hacer sus propias citas. No solo será específico de DB como lo han señalado las personas, sino que las fallas en las citas son la fuente de los errores de inyección SQL.

Si no desea pasar preguntas y valores por separado, pase una lista de parámetros:

def make_my_query(): # ... return sql, (value1, value2) def do_it(): query = make_my_query() cursor.execute(*query)

(Probablemente tenga la sintaxis incorrecta de cursor.exe) El punto aquí es que el hecho de que cursor.execute tome una cantidad de argumentos, eso no significa que deba manejarlos por separado. Puede tratarlos como una sola lista.


Si utiliza django, es posible que desee utilizar la función de cotización que se adapta automáticamente al DBMS configurado actualmente:

from django.db import backend my_quoted_variable = backend.DatabaseOperations().quote_name(myvar)


Bien, entonces tuve curiosidad y fui a ver el origen de psycopg2. Resulta que no tuve que ir más allá de la carpeta de ejemplos :)

Y sí, esto es específico de psycopg2. Básicamente, si solo quieres citar una cadena, harías esto:

from psycopg2.extensions import adapt print adapt("Hello World''; DROP DATABASE World;")

Pero lo que probablemente quiera hacer es escribir y registrar su propio adaptador;

En la carpeta de ejemplos de psycopg2 encontrará el archivo ''myfirstrecipe.py''. Hay un ejemplo de cómo lanzar y citar un tipo específico de una manera especial.

Si tiene objetos para las cosas que desea hacer, puede simplemente crear un adaptador que cumpla con el protocolo ''IPsycopgSQLQuote'' (consulte pydocs para myfirstrecipe.py-example ... en realidad esa es la única referencia que puedo encontrar para ese nombre ) que cita tu objeto y luego lo registra así:

from psycopg2.extensions import register_adapter register_adapter(mytype, myadapter)

Además, los otros ejemplos son interesantes; esp. ''dialtone.py'' y ''simple.py'' .


Su fragmento de código se pondría así, de acuerdo con los documentos de extensión de psycopg.

from psycopg2.extensions import adapt value = "Unsafe string" query = "SELECT * FROM some_table WHERE some_char_field = %s;" % / adapt(value).getquoted() cursor.execute( query ) # value will be correctly quoted, too

La función getquoted devuelve el value como una cadena entre comillas y escapada, por lo que también podría ir: "SELECT * FROM some_table WHERE some_char_field = " + adapt(value).getquoted() .


import re def db_quote(s): return "/"" + re.escape(s) + "/""

puede hacer el trabajo de citas simples que funciona al menos con MySQL. Lo que realmente necesitamos, sin embargo es la función cursor.format () que funcionaría como cursor.execute () excepto que devolvería la consulta resultante en lugar de ejecutarla. Hay momentos en los que no desea que la consulta se ejecute aún, por ejemplo, es posible que desee iniciar sesión primero o imprimirla para la depuración antes de continuar con ella.


Supongo que estás buscando la función de mogrificar .

Ejemplo:

>>> cur.mogrify("INSERT INTO test (num, data) VALUES (%s, %s)", (42, ''bar'')) "INSERT INTO test (num, data) VALUES (42, E''bar'')"


No creo que deles suficiente razonamiento detrás de su evitación para hacer esto de la manera correcta. Utiliza el APi tal como está diseñado y no intentes hacer que tu código sea menos legible para el siguiente tipo y más frágil.