2010-06-28 17 views
19

Mam trudności ze zdobyciem trochę sql w pythonie, aby poprawnie przejść przez MySQLdb. To formatowanie ciągów pythonów, które mnie zabija.Formaty ciągów w języku Python za pomocą znaków wieloznacznych SQL i LIKE

Moja instrukcja sql używa słowa kluczowego LIKE z symbolami wieloznacznymi. Próbowałem wielu różnych rzeczy w Pythonie. Problem polega na tym, że gdy jeden z nich zadziała, w MySQLdb jest linia kodu, która bita na format napisu.

Próba 1:

"SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN tag ON user.id = tag.userId WHERE user.username LIKE '%%s%'" % (query)

Jest to nie udać. Otrzymuję błąd wartość:

ValueError: unsupported format character ''' (0x27) at index 128

Próba 2:

"SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN tag ON user.id = tag.userId WHERE user.username LIKE '\%%s\%'" % (query)

uzyskać ten sam wynik z próby 1.

próba 3:

like = "LIKE '%" + str(query) + "%'" totalq = "SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN tag ON user.id = tag.userId WHERE user.username " + like

to poprawnie tworzy totalq zmienna, ale teraz, gdy idę do uruchomienia kwerendy, otrzymuję błędy z MySQLdb:

File "build/bdist.macosx-10.6-universal/egg/MySQLdb/cursors.py", line 158, in execute query = query % db.literal(args) TypeError: not enough arguments for format string

Próba 4:

like = "LIKE '\%" + str(query) + "\%'" totalq = "SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN tag ON user.id = tag.userId WHERE user.username " + like

Jest to ta sama moc jak próba 3.

To wszystko wydaje się bardzo dziwne. Jak używać symboli wieloznacznych w wyrażeniach sql z pythonem?

+0

Aby echo @bernie poniżej: z dokumentacji psycopg: http://initd.org/psycopg/docs/usage.html#the-problem-z -the-query-parameters: "Nigdy, nigdy, NIGDY nie używaj konkatenacji ciągów w Pythonie (+) lub interpolacja parametrów struny (%) do przekazywania zmiennych do ciągu zapytania SQL. Nawet przy broni palnej. "Oprócz ataków SQL injection, drugą korzyścią jest to, że sterownik" potrafi automatycznie konwertować obiekty Pythona do iz literałów SQL: używając tej funkcji twój kod będzie bardziej niezawodny i niezawodny ". podejście do składu łańcuchów zapytań, np przy użyciu konkatenacji ciągów znaków. " –

Odpowiedz

10

Nie chodzi o ciąg formatowania, ale problemem jest to, w jaki sposób pytania powinny być wykonywane zgodnie z db wymagań operacji w Pythonie (PEP 249)

spróbować czegoś takiego:

sql = "SELECT column FROM table WHERE col1=%s AND col2=%s" 
params = (col1_value, col2_value) 
cursor.execute(sql, params) 

here are some examples for psycog2 gdzie masz jakieś wyjaśnienia to powinno być również poprawne dla mysql (mysqldb również postępuje zgodnie z wytycznymi 2 PEP249 dba api.0: here are examples for mysqldb)

+0

Dzięki, że to zrobiłem. Z jakiegoś powodu pomyślałem MySQL db mógłby dowiedzieć się, jak uciec parametrów nawet wewnątrz instrukcji sql.Ale teraz ma sens rzucić parametry w ten sposób – gngrwzrd

+0

Cieszę się, że ci pomogło! Spędziłem dużo czasu, aż pomyślałem, że jakiś czas temu :) – dzida

6

Aby uciec ampersandy w wyrażeniach formatowania ciąg Python, podwoić ampersanda:

'%%%s%%' % search_string 

EDIT: Ale zdecydowanie zgadzam się z inną odpowiedź. Bezpośrednie zastępowanie ciągów w zapytaniach SQL jest prawie zawsze złym pomysłem.

20

Wszystkie te zapytania wydają się być podatne na ataki typu SQL injection.

Spróbuj coś takiego zamiast:

curs.execute("""SELECT tag.userId, count(user.id) as totalRows 
        FROM user 
      INNER JOIN tag ON user.id = tag.userId 
       WHERE user.username LIKE %s""", ('%' + query + '%',)) 

Jeżeli istnieją dwa argumenty są przekazywane do execute().

+1

To również wygląda na podatne na iniekcje SQL.Aby przejść do sparametryzowanych zapytań przez dowolną bibliotekę do połączenia z bazą danych – jrdioko

+4

@jrdioko: dziękuję za komentarz Uwaga: nie ma faktycznej interpolacji ciągów znaków i że zapytanie * jest * przygotowane przez metodę 'execute()'. – bernie

+0

Przyjmuję to z powrotem, wydaje się, że składnia jest tym, w jaki sposób biblioteka, o której mowa, wykonuje sparametryzowane zapytania. – jrdioko

-1

mam rozwiązanie problemu:

nie można używać:

"SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN tag ON user.id = tag.userId WHERE user.username LIKE '%%s%'" % (query) 

można go zmienić z szablonem ciąg, takich jak:

import MySQLdb 
import string # string module 
....... 
value = {'user':'your value'} 
sql_template = string.Template(""" 
SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN 
tag ON user.id = tag.userId WHERE user.username LIKE '%$user%' 
""") 

sql = sql_template.substitute(value) 

try: 
    cursor.execute(sql) 
    ........... 
except: 
    ........... 
finally : 
    db.close() 
+0

To nie jest lepsze niż bezpośrednia substytucja, której i tak nie powinno się robić. opisz, jak to zrobić poprawnie – Turk