2010-01-19 17 views
13

Sto cercando di assemblare la seguente istruzione SQL utilizzando Python db-API:come generare in modo sicuro un'istruzione SQL come l'utilizzo di python db-api

SELECT x FROM myTable WHERE x LIKE 'BEGINNING_OF_STRING%'; 

dove BEGINNING_OF_STRING dovrebbe essere un pitone var da modo sicuro compilare attraverso la DB-API. Ho provato

beginningOfString = 'abc' 

cursor.execute('SELECT x FROM myTable WHERE x LIKE '%s%', beginningOfString) 
cursor.execute('SELECT x FROM myTable WHERE x LIKE '%s%%', beginningOfString) 

Sono fuori di idee; qual è il modo corretto per farlo?

risposta

20

E 'meglio per separare i parametri da SQL se potete. Quindi è possibile lasciare che il modulo db si occupi della corretta quotatura dei parametri.

sql='SELECT x FROM myTable WHERE x LIKE %s' 
args=[beginningOfString+'%'] 
cursor.execute(sql,args) 
+0

@ ~ unutbu: grazie, lo inchioda. Non avevo pensato di aggiungere semplicemente la% alla stringa stessa * prima * passandola come arg attraverso il db-api. – laramichaels

2

EDIT:

Come hanno notato anche Brian e Thomas, il modo in cui lontano migliore per farlo sarebbe quello di utilizzare:

beginningOfString += '%' 
cursor.execute("SELECT x FROM myTable WHERE x LIKE ?", (beginningOfString,)) 

dal momento che il primo metodo ti lascia aperto ad attacchi SQL injection .


Left in per la storia:

Prova:

cursor.execute("SELECT x FROM myTable WHERE x LIKE '%s%%'" % beginningOfString) 
+3

-1 '" SELEZIONA x FROM myTable WHERE x LIKE '% s %%' "%" doom '; elimina tabella x; seleziona' "' ** Oops? ** – Brian

+0

@Brian; punto molto valido! Mi sono concentrato sull'errore di sintassi; Non avrei dovuto presumere che 'begin' fosse pulito. Grazie per la cattura! –

+0

-1 rimosso. Hai ancora un errore di sintassi, però. Usa le virgolette doppie per la tua stringa e non dovrai sfuggire alle tue virgolette singole. – Brian

-1

Prendere nota di Sqlite3 documentazione:

Di solito le operazioni di SQL dovranno usare valori dalle variabili Python. Non dovresti assemblare la tua query usando le operazioni di stringa di Python perché farlo non è sicuro; rende il vulnerabile a un attacco di iniezione SQL .

Utilizzare invece la sostituzione del parametro del parametro API DB. Mettere ? come segnaposto ovunque si voglia utilizzare un valore, e quindi fornire una tupla di valori come il secondo argomento al metodo execute() del cursore. (Altri moduli di database possono utilizzare un diverso segnaposto, ad esempio% s oppure:. 1) Ad esempio, :

# Never do this -- insecure! 
symbol = 'IBM' 
c.execute("... where symbol = '%s'" % symbol) 

# Do this instead 
t = (symbol,) 
c.execute('select * from stocks where symbol=?', t) 

# Larger example 
for t in [('2006-03-28', 'BUY', 'IBM', 1000, 45.00), 
      ('2006-04-05', 'BUY', 'MSOFT', 1000, 72.00), 
      ('2006-04-06', 'SELL', 'IBM', 500, 53.00), 
     ]: 
    c.execute('insert into stocks values (?,?,?,?,?)', t) 

Penso che si desidera questo:

cursor.execute('SELECT x FROM myTable WHERE x LIKE '%?%', (beginningOfString,)) 
+0

No, quello farà la cosa sbagliata. –

+0

@Thomas: perché? A parte il fatto che ho usato ''%?%'' Invece di ''?%'' (Non era completamente coerente nella sua query che voleva), non vedo alcun problema. – Brian

+5

Il problema è che il? viene rimpiazzato dalla versione * quotata dell'argomento effettivo che passi. Così dato, ad esempio "'; DROP TABLE x; SELECT'" (notare le virgolette singole * e * lì), si finisce con questa domanda ovviamente non valida: SELECT x FROM myTable WHERE x LIKE '%'; DROP TABLE x ; SELEZIONA '%' –