2009-10-14 18 views
8

Potrzebuję wygenerować listę instrukcji wstawiania (dla postgresql) z plików html, czy jest dostępna biblioteka dla Pythona, która pomoże mi właściwie uciec i podać nazwy/wartości? w PHP używam PDO, aby wykonać ucieczkę i cytowanie, czy istnieje odpowiednik biblioteki dla Pythona?Generowanie instrukcji SQL z pythonem

Edit: muszę wygenerować plik SQL do wykonania później

+7

Generowanie "zwykłych instrukcji SQL" z danymi in-line jest z natury podatne na awarie bezpieczeństwa z powodów tak abstrakcyjnych, jak różne interpretacje znaków Unicode między silnikiem bazy danych a biblioteką generującą dane. To NIE jest coś, co powinieneś spróbować zrobić. Dlatego dane wyjściowe powinny być sformułowane - i przekazane do interfejsu API bazy danych - jako kombinacja ciągu znaków/listy danych. SQLAlchemy zautomatyzuje to. –

+0

Rozumiem, ale przypadek użycia generował plik SQL do wykonania później: – Jeffrey04

+0

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

Odpowiedz

2

Na solidności, polecam za pomocą sprawozdań przygotowanych do wysłania wartości wprowadzone przez użytkownika, bez względu na język używasz. :-)

+0

Czy istnieje już biblioteka do tego? Chcę, aby zwykłe instrukcje SQL były jako wynikowe :) – Jeffrey04

1

Metoda python db api 2.0 ma metodę ".execute" dla obiektów połączeń. Możesz określić parametry (użyj przecinka NIE znaku%, aby oddzielić parametry od ciągu zapytania) za pomocą tej funkcji.

10

SQLAlchemy zapewnia a robust expression language do generowania kodu SQL z języka Python.

Jednak, jak w każdej dobrze zaprojektowanej warstwie abstrakcji, zapytania generują dane wstawiania za pomocą zmiennych wiążących, a nie poprzez próbę połączenia języka zapytań z danymi wstawianymi do pojedynczego ciągu znaków. Takie podejście pozwala uniknąć ogromnych luk w zabezpieczeniach i jest w przeciwnym razie właściwym rozwiązaniem.

+0

Link jest martwy. Myślę, że jest to odpowiedni dokument: http://docs.sqlalchemy.org/en/latest/core/expression_api.html – Chris

+0

@phasetwenty, dzięki, zaktualizowany (pięć lat później, heh). –

+0

Myślę, że jest martwy jeszcze raz –

1

Cytowanie parametrów ręcznie w ogóle jest złym pomysłem. A co jeśli w regułach ucieczki pojawia się błąd? Co jeśli ucieczka nie pasuje do używanej wersji DB? Co się stanie, jeśli zapomnisz ominąć jakiś parametr lub błędnie założyłeś, że nie może zawierać danych wymagających ucieczki? To wszystko może spowodować lukę SQL injection. Ponadto, DB może mieć pewne ograniczenia dotyczące długości instrukcji SQL, podczas gdy trzeba przekazać duże porcje danych dla kolumny LOB. Dlatego Python DB API i większość baz danych (moduł API Pythona DB będzie przejrzysty uciec parametry, jeśli baza danych nie obsługuje tej funkcji, podobnie jak wcześnie MySQLdb) umożliwiają przekazanie parametrów oddzielonych od stwierdzenia:

.Execute (operacja [, parametry])

+2

Rozumiem, ale chcę tylko listę instrukcji sql (nie wykonując ich) – Jeffrey04

13

Wiem, że to stare pytanie, ale często chciałem, co wydaje się, że OP chce: BARDZO prosta biblioteka do generowania podstawowego SQL.

Poniższe funkcje właśnie to robią. Podajesz im nazwę tabeli i słownik zawierający dane, których chcesz użyć, i zwracają zapytanie SQL dla potrzebnej operacji.

Pary klucz/wartość reprezentują nazwy pól i wartości w wierszach bazy danych.

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) 

Używasz tego jak ty.Wystarczy nadać mu nazwę tabeli i słownik (lub użyj ** kwargs cechę python):

>>> 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';" 

ale uwaga Ataki SQL Injection

Spójrz, co się dzieje, gdy użytkownik złośliwy kod czyni to:

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

łatwo jest zrobić własną prowizoryczną ORM ale dostajesz tylko to, co widzisz - trzeba uciec wejściu siebie :)