2009-05-23 13 views
49

Ok quindi non sono così esperto in Python.Come utilizzare le variabili nell'istruzione SQL in Python?

Ho il seguente codice Python:

cursor.execute("INSERT INTO table VALUES var1, var2, var3,") 

dove var1 è un intero, var2 & var3 sono stringhe.

Come posso scrivere i nomi delle variabili senza python includendoli come parte del testo della query?

risposta

57
cursor.execute("INSERT INTO table VALUES (%s, %s, %s)", (var1, var2, var3)) 

Si noti che i parametri vengono passati come una tupla.

L'API del database esegue correttamente l'escaping e il quoting delle variabili. Fare attenzione a non utilizzare l'operatore formattazione delle stringhe (%), perché

  1. Non fa alcuna fuga o di citazione.
  2. è soggetto a attacchi di formato stringa non controllati, ad es. SQL injection.
+0

Interessante, perché funziona con i vars separatamente invece che in un array (var1, var2, var3)? – Andomar

+0

Secondo le specifiche API DB, sembra che possa essere in entrambi i modi: http://www.python.org/dev/peps/pep-0249/ –

+0

http://docs.python.org/2/library/ sqlite3.html # Escaping – earthmeLon

16

http://www.amk.ca/python/writing/DB-API.html

Fare attenzione quando è sufficiente aggiungere valori delle variabili per le sue dichiarazioni: Immaginate un utente denominazione stesso ';DROP TABLE Users;' - è per questo che è necessario utilizzare SQL fuga, che Python fornisce per voi quando si usa il cursore. Esegui in maniera decente. Esempio nella url è:

cursor.execute("insert into Attendees values (?, ?, ?)", (name, 
seminar, paid)) 
+7

In realtà, non è l'escape di SQL. È un binding variabile, che è molto più semplice e diretto. I valori sono associati all'istruzione SQL dopo l'analisi, rendendolo immune a qualsiasi attacco di iniezione. –

+0

"Little Bobby Tables, lo chiamiamo". Disinfetta i tuoi input. https://xkcd.com/327/ – mattmc3

40

diverse implementazioni del Python DB-API sono autorizzati a utilizzare diversi segnaposto, quindi avrete bisogno di scoprire che quello che si sta utilizzando - potrebbe essere (ad esempio con MySQLdb):

cursor.execute("INSERT INTO table VALUES (%s, %s, %s)", (var1, var2, var3)) 

o (ad esempio con sqlite3 dalla libreria standard di Python):

cursor.execute("INSERT INTO table VALUES (?, ?, ?)", (var1, var2, var3)) 

o altri ancora (dopo VALUES si potrebbe avere (:1, :2, :3), o "stili nominati" (:fee, :fie, :fo) o (%(fee)s, %(fie)s, %(fo)s) dove si passa un DIT anziché una mappa come secondo argomento a execute). Controlla la costante di stringa paramstyle nel modulo API DB che stai utilizzando e cerca paramstyle allo http://www.python.org/dev/peps/pep-0249/ per vedere quali sono tutti gli stili che passano i parametri!

+0

È possibile fare la stessa cosa ma con lo script SQL esterno? – Novitoll

19

Molti modi. NON utilizzare il più ovvio (%s con %) nel codice reale, è aperto a attacks.

Qui copia-paste'd from pydoc of sqlite3:

# Never do this -- insecure! 
symbol = 'RHAT' 
c.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol) 

# Do this instead 
t = ('RHAT',) 
c.execute('SELECT * FROM stocks WHERE symbol=?', t) 
print c.fetchone() 

# Larger example that inserts many records at a time 
purchases = [('2006-03-28', 'BUY', 'IBM', 1000, 45.00), 
      ('2006-04-05', 'BUY', 'MSFT', 1000, 72.00), 
      ('2006-04-06', 'SELL', 'IBM', 500, 53.00), 
      ] 
c.executemany('INSERT INTO stocks VALUES (?,?,?,?,?)', purchases) 

Più esempi se avete bisogno di:

# Multiple values single statement/execution 
c.execute('SELECT * FROM stocks WHERE symbol=? OR symbol=?', ('RHAT', 'MSO')) 
print c.fetchall() 
c.execute('SELECT * FROM stocks WHERE symbol IN (?, ?)', ('RHAT', 'MSO')) 
print c.fetchall() 
# This also works, though ones above are better as a habit as it's inline with syntax of executemany().. but your choice. 
c.execute('SELECT * FROM stocks WHERE symbol=? OR symbol=?', 'RHAT', 'MSO') 
print c.fetchall() 
# Insert a single item 
c.execute('INSERT INTO stocks VALUES (?,?,?,?,?)', ('2006-03-28', 'BUY', 'IBM', 1000, 45.00)) 
+0

Alcune delle implementazioni dell'API DB utilizzano effettivamente% s per le loro variabili, in particolare psycopg2 per PostgreSQL. Questo non deve essere confuso (sebbene sia facilmente) con l'utilizzo di% s con l'operatore% per la sostituzione delle stringhe. Sarebbe davvero bello se, per la portabilità, potremmo avere solo un modo standard definito di specificare i parametri SQL per DB-API. – ThatAintWorking

Problemi correlati