2012-01-12 7 views
13

Używanie pysqlite Tworzę procedurę, by zrobić coś z pewnymi danymi. Ten sam rodzaj pracy odbywa się na podobnych polach w wielu tabel i kolumn, więc pomyślałem, że mógłbym parametryzacji sql, jak pokazano poniżej:pysqlite: Zastępowanie zastępcze dla nazw kolumn lub tabel?

def foo(): 
    column = 'c' 
    table = 't' 
    row = 1 
    # preferred approach, gives syntax error 
    c.execute('SELECT ? FROM ? WHERE id=?', (column, table, row)) 
    # sanity check, works fine 
    c.execute('SELECT c FROM t WHERE id=?', (row)) 
    # workaround, also works, but is this the right way? 
    c.execute('SELECT % FROM % WHERE id=?' % (column, table), row)) 

Błąd pojawia nie jest bardzo pomocny (sqlite3.OperationalError: near "?": syntax error), ale zdobądź punkt: Pysqlite nie docenia, że ​​w ten sposób używane są symbole zastępcze.

Czy ktoś może wskazać, co się tutaj dzieje, wraz z właściwym sposobem postępowania?

Odpowiedz

15

Po prostu nie można używać symboli zastępczych dla nazw kolumn lub tabel. Nie mam na to autorytatywnego wzmianki - "znam to" tylko dlatego, że próbowałem i od upadku. To sprawia, że ​​chociaż jakiś sens:

  • Jeśli kolumny i stół może być parametryzowane, nie byłoby niewiele celem do przygotowania (execute -ing) instrukcji SQL przed pobraniem, ponieważ wszystkie części zestawienia mogą być zastąpione .
  • Nie jestem pewien co do pysqlite , ale MySQLdb automatycznie cytuje wszystkie parametry ciągów . Nazwy kolumn i tabel nie powinny być cytowane. Czyli komplikowałoby parsowanie wymagane przez sterownik, gdyby musiało ono do zdecydować, czy symbol zastępczy reprezentuje nazwę kolumny lub tabeli, a nie wartość , która wymaga cytowania.

Krótko mówiąc, znalazłeś właściwą drogę - użyj formowania ciągów znaków.

c.execute('SELECT {} FROM {} WHERE id=?'.format(column, table), row)) 

Nie wszystkie sterowniki zacytować parametry - oursql nie robi, ponieważ wysyła SQL i argumenty do serwera oddzielnie.

+0

Czy jest to bezpieczne z iniekcji SQL? – berkelem

+1

@berkelem: Jest podatny na wstrzyknięcia SQL. Niestety, ponieważ nazwy kolumn i tabel są nierozerwalne, nie ma możliwości uniknięcia formatowania ciągów. [Używanie białych list] (https://phpdelusions.net/sql_injection#whitelist) jest tutaj najlepszą praktyką. – unutbu

2

Po udzieleniu odpowiedzi @unutbu nie ma możliwości użycia symboli zastępczych dla nazw tabel/kolumn. Moja sugestia, aby zrobić to, co teraz robisz, ale także podać nazwy tabel, aby zabezpieczyć się przed tabelą lub kolumną, które mogą mieć nieparzystą nazwę.

What does the SQL Standard say about usage of backtick(`)? wyjaśnia to już w pewnym stopniu i pomimo opinii w tej odpowiedzi powiedziałbym, że w twoim przypadku cytowanie jest dobrym pomysłem.

Powiązane problemy