2012-01-12 9 views
13

Uso de pysqlite Estoy haciendo un procedimiento para hacer algo con algunos datos. El mismo tipo de operación se realiza en campos similares en varias tablas y columnas, así que pensé que podía parametrizar la instrucción SQL como se muestra a continuación:pysqlite: sustitución de marcadores de posición para nombres de columnas o tablas?

def foo(): 
    column = 'c' 
    table = 't' 
    row = 1 
    # preferred approach, gives syntax error 
    c.execute('SELECT ? FROM ? WHERE id=?', (column, table, row)) 
    # sanity check, works fine 
    c.execute('SELECT c FROM t WHERE id=?', (row)) 
    # workaround, also works, but is this the right way? 
    c.execute('SELECT % FROM % WHERE id=?' % (column, table), row)) 

El error que consigo no es muy útil (sqlite3.OperationalError: near "?": syntax error), pero entérate: Pysqlite no aprecia que los marcadores de posición se usen de esta manera.

¿Alguien puede señalar lo que está sucediendo aquí junto con la forma correcta de hacer lo anterior?

Respuesta

15

Simplemente no puede usar marcadores de posición para nombres de columnas o tablas. No tengo una cita autorizada para esto; lo "sé" solo por haberlo intentado y haber fracasado. Hace algún sentido de que:

  • Si las columnas y la tabla podrían ser parametrizados, habría poca propósito de preparar (execute ing) la instrucción SQL antes de ir a buscar, ya que todas las partes de la declaración podría ser reemplazadas .
  • No estoy seguro acerca de pysqlite , pero MySQLdb cita automáticamente todos los parámetros de cadena . Los nombres de columna y tabla no se deben citar. Por lo tanto, complicaría el análisis requerido por el controlador si tuviera que decidir si un marcador de posición representa un nombre de columna o tabla frente a un valor de que debe citarse.

En resumen, has encontrado la manera correcta: utiliza el formateo de cuerdas.

c.execute('SELECT {} FROM {} WHERE id=?'.format(column, table), row)) 

No todos los controladores citan parámetros - oursql no es así, ya que envía SQL y argumentos al servidor por separado.

+0

¿Esto es seguro desde la inyección SQL? – berkelem

+1

@berkelem: es vulnerable a la inyección SQL. Desafortunadamente, debido a que los nombres de las columnas y las tablas no son parametrizables, no hay forma de evitar el formato de cadenas. [Usar listas blancas] (https://phpdelusions.net/sql_injection#whitelist) es una buena práctica aquí. – unutbu

2

Como respondió @unutbu, no hay forma de usar marcadores de posición para nombres de tabla/columna. Mi sugerencia de hacer lo que está haciendo ahora, pero también citar los nombres de la tabla para protegerse de una tabla o columna que podría tener un nombre extraño.

What does the SQL Standard say about usage of backtick(`)? ya lo explica en cierta medida, ya pesar de la opinión en esa respuesta, diría que en su caso, citar es una buena idea.

Cuestiones relacionadas