2012-01-12 17 views
13

Utilizzo di pysqlite Sto facendo una procedura per fare qualcosa con alcuni dati. Lo stesso tipo di operazione viene eseguita su campi simili in più tabelle e colonne, così ho pensato che potrei parametrizzare l'istruzione SQL come illustrato di seguito:pysqlite: sostituzione segnaposto per nomi di colonne o tabelle?

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

L'errore che ottengo non è molto utile (sqlite3.OperationalError: near "?": syntax error), ma io ottenere il punto: Pysqlite non apprezza i segnaposto utilizzati in questo modo.

Qualcuno può indicare cosa sta succedendo qui insieme al modo corretto di fare quanto sopra?

risposta

15

Semplicemente non è possibile utilizzare i segnaposti per i nomi di colonne o tabelle. Non ho una citazione autoritativa per questo - lo "so" solo per averlo provato e fallito. Fa un certo senso però:

  • Se le colonne e la tabella potrebbe essere parametrizzate, ci sarebbe poco scopo di preparare (execute -ing) l'istruzione SQL prima del recupero, dal momento che tutte le parti della dichiarazione potrebbero essere sostituiti .
  • io non sono sicuro di pysqlite , ma MySQLdb cita automaticamente tutti i parametri di stringa . I nomi di colonne e tabelle non dovrebbero essere citati. Quindi complicherebbe l'analisi richiesta dal driver se avesse dovuto decidere se un segnaposto rappresentasse una colonna o un nome di tabella rispetto a un valore che necessitasse di virgolette.

In breve, hai trovato la strada giusta: utilizzare la formattazione di stringhe.

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

Non tutti i driver citare parametri - oursql non lo fa, dal momento che manda SQL e gli argomenti al server separatamente.

+0

È sicuro dall'iniezione SQL? – berkelem

+1

@berkelem: è vulnerabile all'iniezione SQL. Sfortunatamente, poiché i nomi di colonne e tabelle non sono parametrizzabili, non c'è modo di evitare la formattazione delle stringhe. [Usare le whitelist] (https://phpdelusions.net/sql_injection#whitelist) è una buona pratica qui. – unutbu

2

Come ha risposto @unutbu, non è possibile utilizzare i segnaposto per i nomi tabella/colonna. Il mio suggerimento di fare ciò che state facendo ora, ma anche di citare i nomi delle tabelle per proteggervi da una tabella o colonna che potrebbe avere un nome strano.

What does the SQL Standard say about usage of backtick(`)? lo spiega già in una certa misura e, nonostante l'opinione in quella risposta, direi che nel tuo caso, la citazione è una buona idea.

Problemi correlati