2012-10-11 5 views
6

Desidero passare i parametri di query al metodo cursor.execute() di MySQLdb come dizionario con nome, in modo che siano con escape dall'iniezione SQL.Python MySQLdb: parametri di query come dizionario con nome

si può spiegare il motivo per cui questo dà KeyError:

>>>c.execute('select id from users where username=%(user)s', {'user':'bob',}) 
KeyError: 'user' 

manuale MySQLdb http://mysql-python.sourceforge.net/MySQLdb.html dice:

* paramstyle

costante stringa che specifica il tipo di marcatore di parametro formattazione atteso dall'interfaccia. Impostare su "formato" = codici di formato printf ANSI C, ad es. '... WHERE name =% s'. Se viene utilizzato un oggetto di mapping per conn.execute(), l'interfaccia utilizza effettivamente "pyformat" = codici di estensione del codice Python, ad es. '... WHERE name =% (name) s'. Tuttavia, l'API non attualmente consente la specificazione di più di uno stile in paramstyle *

risposta

6

La linea nella documentazione seguendo ciò che si è incollato può rispondere alla tua domanda:.

Parameter placeholders can only be used to insert column values. They can not be used for other parts of SQL, such as table names, statements, etc.

+0

Sto inserendo un valore *** di colonna ***. La riga nella documentazione indica che il seguente codice non è valido: 'c.execute ('seleziona id da% s dove username =% s', ('users', 'bob'))' – mercador

+1

@mercador Right, the 'dal pezzo di% s' è ciò che sta causando l'errore dal momento che si sta tentando di parametrizzare il nome della tabella. Il vantaggio dell'uso di 'execute' in questo modo è che aiuta a prevenire l'SQL injection, ma se si adottano le opportune precauzioni di sicurezza (che non sono un esperto, ma comportano una corretta sanitizzazione/fuga dei parametri), è possibile usa la formattazione di stringhe incorporate di Python per costruire la query e poi passala a 'execute'. Ancora una volta, l'iniezione SQL è la preoccupazione principale. Spero che questo ti aiuti! – RocketDonkey

5

MySQLdb permette dicts come parametri di query . This response mostra tutti i diversi modi per farlo. Hai solo bisogno di fornire una sicurezza come parametro (tupla, dict ...) come secondo parametro da "eseguire". NON formattare la query come solo un parametro per eseguire il metodo "execute" o verrai probabilmente esposto a attacchi di SQL injection. Vedi:

"SELECT * FROM users WHERE username = '%s'" % (user) 

pensare a cosa sarebbe successo se:

user = "peter;DROP TABLE users" :_(

L'altro modo è assicurato in quanto consente la biblioteca MySQLdb per gestire il controllo necessario.

Non so che cosa è sbagliato, perché la query funziona bene per me:

# Connect to db 
# Open a cursor 
stmt = "SELECT * FROM users WHERE username = %(user)s" 
cursor.execute(stmt, {"user": "bob"}) 
user = cursor.fetchone() 
print user 

{'username': 'bob', 'alias': 'bobby', 'avatar': 'default', 'fullname': 'bob'} 

Puoi darci maggiori informazioni?