2009-10-14 14 views
8

Ho bisogno di generare un elenco di istruzioni di inserimento (per postgresql) da file html, c'è una libreria disponibile per Python per aiutarmi correttamente a evadere e citare i nomi/valori? in PHP uso PDO per eseguire l'escaping e il quoting, esiste una libreria equivalente per python?Genera istruzioni SQL con python

Edit: Ho bisogno di generare un file con le istruzioni SQL per l'esecuzione successiva

+7

Generare "semplici istruzioni SQL" con dati in linea è intrinsecamente soggetto a errori di sicurezza per ragioni astratte come interpretazioni variabili di caratteri Unicode tra il motore di database e la libreria che sta generando. NON è qualcosa che dovresti provare a fare. L'output, quindi, deve essere espresso in frasi e passato all'API del database come stringa di query/lista dati combinata. SQLAlchemy lo automatizzerà. –

+0

Capisco, ma il caso d'uso stava generando un file SQL da eseguire successivamente – Jeffrey04

+0

http://stackoverflow.com/questions/309945/how-to-quote-a-string-value-explicitly-python-db-api- psycopg2 –

risposta

2

Per robustezza, mi consiglia di utilizzare le istruzioni preparate per inviare i valori immessi dall'utente, indipendentemente dalla lingua che si usa. :-)

+0

c'è già una libreria per farlo? Voglio istruzioni SQL semplici come output però :) – Jeffrey04

1

Il python db api 2.0 ha un metodo ".execute" per oggetti di connessione. È possibile specificare i parametri (utilizzare una virgola NON un segno% per separare i parametri dalla stringa di query) con questa funzione.

10

SQLAlchemy fornisce a robust expression language per generare SQL da Python.

Come ogni altro livello di astrazione ben progettato, tuttavia, le query genera dati di inserimento tramite variabili di bind piuttosto che attraverso il tentativo di mescolare il linguaggio di query e i dati inseriti in una singola stringa. Questo approccio evita enormi vulnerabilità di sicurezza ed è altrimenti The Right Thing.

+0

Link is dead. Penso che questo sia il documento rilavant: http://docs.sqlalchemy.org/en/latest/core/expression_api.html – Chris

+0

@phasetwenty, grazie, aggiornato (cinque anni dopo, heh). –

+0

Penso che sia morto di nuovo –

1

La quotazione manuale dei parametri in generale è una cattiva idea. Cosa succede se c'è un errore nell'escaping delle regole? Cosa succede se l'escape non corrisponde alla versione del DB utilizzata? Cosa succede se ti dimentichi di sfuggire a qualche parametro o erroneamente presume che non possa contenere dati che richiedono l'escape? Tutto ciò potrebbe causare la vulnerabilità di SQL injection. Inoltre, DB può avere alcune restrizioni sulla lunghezza dell'istruzione SQL mentre è necessario passare un grosso blocco di dati per la colonna LOB. Ecco perché Python DB API e la maggior parte dei database (modulo API Python DB in modo trasparente sfuggire parametri, se il database non supporta questo, come ha fatto all'inizio del MySQLdb) consentire parametri separati dalla dichiarazione di passaggio:

.execute (operazione [, parametri])

+2

Capisco, ma voglio solo una lista di istruzioni SQL (non eseguendole) – Jeffrey04

13

So che questa è una vecchia domanda, ma ho spesso desiderato ciò che sembra l'OP desidera: Una libreria MOLTO semplice per generare SQL di base.

Le funzioni seguenti fanno proprio questo. Dagli un nome di tabella e un dizionario contenente i dati che desideri utilizzare e restituiscono la query SQL per l'operazione necessaria.

Le coppie chiave/valore rappresentano i nomi dei campi e i valori nelle righe del database.

def read(table, **kwargs): 
    """ Generates SQL for a SELECT statement matching the kwargs passed. """ 
    sql = list() 
    sql.append("SELECT * FROM %s " % table) 
    if kwargs: 
     sql.append("WHERE " + " AND ".join("%s = '%s'" % (k, v) for k, v in kwargs.iteritems())) 
    sql.append(";") 
    return "".join(sql) 


def upsert(table, **kwargs): 
    """ update/insert rows into objects table (update if the row already exists) 
     given the key-value pairs in kwargs """ 
    keys = ["%s" % k for k in kwargs] 
    values = ["'%s'" % v for v in kwargs.values()] 
    sql = list() 
    sql.append("INSERT INTO %s (" % table) 
    sql.append(", ".join(keys)) 
    sql.append(") VALUES (") 
    sql.append(", ".join(values)) 
    sql.append(") ON DUPLICATE KEY UPDATE ") 
    sql.append(", ".join("%s = '%s'" % (k, v) for k, v in kwargs.iteritems())) 
    sql.append(";") 
    return "".join(sql) 


def delete(table, **kwargs): 
    """ deletes rows from table where **kwargs match """ 
    sql = list() 
    sql.append("DELETE FROM %s " % table) 
    sql.append("WHERE " + " AND ".join("%s = '%s'" % (k, v) for k, v in kwargs.iteritems())) 
    sql.append(";") 
    return "".join(sql) 

Lo si utilizza così.Basta dare un nome di tabella e un dizionario (o usare il ** kwargs caratteristica del pitone):

>>> upsert("tbl", LogID=500, LoggedValue=5) 
"INSERT INTO tbl (LogID, LoggedValue) VALUES ('500', '5') ON DUPLICATE KEY UPDATE LogID = '500', LoggedValue = '5';" 

>>> read("tbl", **{"username": "morten"}) 
"SELECT * FROM tbl WHERE username = 'morten';" 

>>> read("tbl", **{"user_type": 1, "user_group": "admin"}) 
"SELECT * FROM tbl WHERE user_type = '1' AND user_group = 'admin';" 

ma attenzione di attacchi SQL injection

Guardate cosa succede quando un utente malintenzionato del codice fa questo:

>>> read("tbl", **{"user_group": "admin'; DROP TABLE tbl; --"}) 
"SELECT * FROM tbl WHERE user_group = 'admin'; DROP TABLE tbl; --';" 

E 'facile fare il proprio ORM di fortuna ma si ottiene solo ciò che si vede - si deve sfuggire l'ingresso da soli :)