DB API - Parameter übergeben bei "WHERE ... IN"

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

wie die Übergabe von Parametern grundsätzlich funktioniert ist klar (MySQL):

Code: Alles auswählen

ersatz = 'egg'
c.execute("SELECT foo FROM bar WHERE spam LIKE %s", ersatz)
Jetzt will ich das aber mit einer "WHERE ... IN ..." Abfrage machen - und es klappt nicht... :(

Code: Alles auswählen

ersatz ='egg1, egg2'
c.execute("SELECT foo FROM bar WHERE spam IN %s", ersatz)
Egal wie ich Ersatz formatiere (wie oben, als Liste, "'egg1',egg2'" usw.) - Python wirft immer den SQL-Error "SQL-Syntax".
Ich vermute es liegt darin, die " bzw ' im bei der Parameter-Übergabe escaped werden...

Weiß jemand, wie man das macht?

Gruß, noisefloor
Zuletzt geändert von noisefloor am Dienstag 3. August 2010, 06:33, insgesamt 1-mal geändert.
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

Nachtrag: Wenn man es mit der "bösen" ;-) String Ersetzung macht funktioniert es so:

Code: Alles auswählen

ersatz="egg1','egg2"
c.execute("SELECT foo FROM bar WHERE spam LIKE '%s' ") %ersatz)
Aber, wie gesagt, das auf die Parameter-Ersetzung zu transferieren kriege ich nicht hin...

Gruß, noisefloor
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

noisefloor hat geschrieben: Egal wie ich Ersatz formatiere (wie oben, als Liste, "'egg1',egg2'" usw.) - Python wirft immer den SQL-Error "SQL-Syntax".
Also hast Du so was schon probiert? Wäre für mich jetzt das naheliegenste...

Code: Alles auswählen

ersatz = ('egg1', 'egg2')
c.execute("SELECT foo FROM bar WHERE spam IN %s", ersatz)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

noisefloor hat geschrieben:

Code: Alles auswählen

ersatz ='egg1, egg2'
c.execute("SELECT foo FROM bar WHERE spam IN %s", ersatz)
Geht es auch dann nicht, wenn du die von der SQL-Syntax her erforderlichen runden Klammern verwendest?

Code: Alles auswählen

SELECT foo FROM bar WHERE spam IN (%s)
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

ja, ich habe schon alle möglichen (abenteuerlichen) Kombis aus ' " und ( ) probiert.

Der Punkt ist: Die o.g. Version funktionieren in sofern, dass kein SQL-Fehler geworfen wird - aber das Ergebnis der Abfrage ist leer. Ist es aber in Wirklichkeit nicht. Heißt, wenn ich den SQL Query "von Hand" eingebe, also ohne Parameter-Ersetzung, gibt es ein Ergebnis (was auch richtig ist).

Sprich, irgendwie läuft da irgendwas schief bei der Parameterersetzung.

Weiß jemand, wie ob es da Möglichkeiten zum Debuggen gibt, also sowas wie den letzten Query anzeigen lassen (alles unter MySQL).

Gruß, noisefloor
BlackJack

@noisefloor: Die Parameterersetzung ersetzt einen *einzelnen* Platzhalter sicher mit einem *einzelnen* Wert. Man kann nicht einen Platzhalter durch mehrere Werte ersetzen, auch wenn der nach dem SQL-Test ``IN`` steht. Der Witz bei der sicheren Ersetzung ist ja gerade das Zeichen mit syntaktischer Bedeutung in SQL wie ',' oder ';' eben *nicht* zur SQL-Injektion verwendet werden können.

Vielleicht nicht so schön (und ungetestet):

Code: Alles auswählen

ersatz = ('egg1', 'egg2')
cursor.execute('SELECT foo'
               ' FROM bar'
               ' WHERE spam IN (%s)' % (','.join(['%s'] * len(ersatz))),
               ersatz)
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

@BlackJack: jetzt wo du es so sagst - das macht ja auch Sinn. Immerhin lag ich mit meiner Vermutung richtig, dass der Query nicht funktioniert, weil was "weg-escaped" wird. :-)

Die String-Ersetzung ist in diesem (meinem Fall) auch nicht soo kritisch, weil ich keine Nutzer-Eingabe durch reiche.

Gruß, noisefloor
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

noisefloor hat geschrieben:Die String-Ersetzung ist in diesem (meinem Fall) auch nicht soo kritisch, weil ich keine Nutzer-Eingabe durch reiche.
Dennoch, ich wuerde mir so einen Stil gar nicht erst angewoehnen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

ja nee - ich nehme ja auch die Parameter wo es geht.

Im o.g. Fall geht es aber scheinbar nicht... Vielleicht sollte ich ein PEP für die Python DB API 3.0 einreichen... ;-)

Gruß, noisefloor
BlackJack

@noisefloor: Von welchem Fall reden wir gerade? Ich habe in meinem Beispiel keine Zeichenkettenformatierung für die *Werte* verwendet.
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

@BlackJack: Yo, stimmt... Hatte das Beispiel zuerst falsch interpretiert :roll: - jetzt habe ich es aber verstanden. Werde ich später mal probieren. :-)

Gruß, noisefloor
Antworten