2010-06-28 5 views
19

Ich habe es schwer, einige SQL in Python zu bekommen, um MySQLdb richtig zu durchlaufen. Es ist Pythons Zeichenfolge Formatierung, die mich tötet.Python-String-Formate mit SQL-Wildcards und LIKE

Meine SQL-Anweisung verwendet das Schlüsselwort LIKE mit Platzhaltern. Ich habe in Python verschiedene Dinge ausprobiert. Das Problem ist, sobald ich einen von ihnen zum Laufen bringe, gibt es eine Codezeile in MySQLdb, die das String-Format rülpst.

Versuch 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)

Dies ist ein no go. Ich erhalte Wertfehler:

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

Versuch 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)

ich das gleiche Ergebnis von Versuch abrufen 1.

Versuch 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

Das korrekte totalq schafft Variable, aber jetzt, wenn ich gehe, um die Abfrage auszuführen, bekomme ich Fehler von 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

Versuch 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

Dies ist die gleiche Ausgabe wie Versuch 3.

Das alles wirklich seltsam scheint. Wie kann ich Platzhalter in SQL-Anweisungen mit Python verwenden?

+0

zu echo @bernie unten: Von psycopg docs: http://initd.org/psycopg/docs/usage.html#the-problem-with-the-query-parameters: "Nie, nie, niemals Python String-Verkettung (+) oder String-Parameter-Interpolation (%), um Variablen an eine SQL-Abfragezeichenfolge zu übergeben. Nicht einmal mit vorgehaltener Waffe. "Ein weiterer Vorteil neben SQL-Injection-Angriffen ist, dass der Treiber" Python-Objekte automatisch von und in SQL-Literale konvertieren kann: Mit dieser Funktion wird Ihr Code robuster und zuverlässiger. "Dies ist ein" naives " Ansatz für die Zusammensetzung von Abfrage-Strings, z " –

Antwort

10

Es geht nicht um String-Formatierung, aber das Problem ist, wie Abfragen sollten (PEP 249)

versuchen so etwas wie dies nach db Betriebsanforderungen in Python ausgeführt werden:

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, wo Sie einige Erklärungen haben das sollte auch für mysql gelten (mysqldb folgt auch PEP249 dba api guidance 2.0: here are examples for mysqldb)

+0

Danke. Das hat es getan. Aus irgendeinem Grund dachte ich MySQL db würde herausfinden, wie man Parameter innerhalb der SQL-Anweisung entkommt, aber jetzt macht es Sinn, Parameter wie folgt zu übergeben: – gngrwzrd

+0

Ich bin froh, dass es dir geholfen hat Ich habe viel Zeit verbracht, bis ich das vor einiger Zeit herausgefunden habe :) – dzida

6

Um Et-Zeichen in Python-String Formatierung Ausdrücke zu entkommen, die doppelte kaufmännische Und:

'%%%s%%' % search_string 

Edit: Aber ich mit einer anderen Antwort auf jeden Fall zustimmen. Direkte String-Substitution in SQL-Abfragen ist fast immer eine schlechte Idee.

20

Diese Abfragen scheinen alle anfällig für SQL-Injection-Angriffe zu sein.

Versuchen etwas Ähnliches statt:

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 + '%',)) 

Wo gibt es zwei Argumente werden zu execute() geben.

+1

Das sieht auch anfällig für SQL-Injektion. Verwenden von parametrisierten Abfragen durch welche Bibliothek verwendet wird, um eine Verbindung mit der Datenbank herzustellen ist der Weg zu gehen. – jrdioko

+4

@ jrdioko: Danke für Ihren Kommentar. Beachten Sie, dass es keine eigentliche String-Interpolation ist , und dass die Abfrage * durch die Methode 'execute()' * vorbereitet wird. – bernie

+0

Ich nehme das zurück, es scheint, dass Syntax die Frage ist, wie die betreffende Bibliothek parametrisierte Abfragen ausführt. " – jrdioko

-1

Ich habe eine Lösung für Ihr Problem:

Sie können nicht verwenden:

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

Sie es mit Zeichenketten-Template ändern können, wie zum Beispiel:

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

Dies ist nicht besser als eine direkte Substitution, die Sie ohnehin nicht tun sollten.Platzhalter wie oben beschrieben und in den PEP 249 Dokumenten Beschreiben Sie, wie Sie das richtig machen – Turk