Seltsame SQLAlchemy-Fehlermeldung: TypeError: Das Objekt 'dict' unterstützt keine Indizierung

145

Ich verwende handgefertigtes SQL, um mithilfe von SqlAlchemy Daten aus einer PG-Datenbank abzurufen. Ich versuche eine Abfrage, die den SQL-ähnlichen Operator '%' enthält und SqlAlcjhemy durch eine Schleife zu werfen scheint:

sql = """
       SELECT DISTINCT u.name from user u
        INNER JOIN city c ON u.city_id = c.id
        WHERE c.designation=upper('fantasy') 
        AND c.id IN (select id from ref_geog where short_name LIKE '%opt')
      """

# The last line in the above statement throws the error mentioned in the title. 
# However if the last line is change to:
# AND c.id IN (select id from ref_geog where short_name = 'helloopt')
# the script runs correctly.
#
# I also tried double escaping the '%' i.e. using '%%' instead - that generated the same error as previously.

connectDb()
res = executeSql(sql)
print res
closeDbConnection()

Weiß jemand, was diese irreführende Fehlermeldung verursacht und wie ich sie beheben kann?

[[Bearbeiten]]

Bevor jemand fragt, gibt es nichts Besonderes oder Besonderes an den oben enthaltenen Funktionen. Zum Beispiel ruft die Funktion executeSql () einfach conn.execute (sql) auf und gibt die Ergebnisse zurück. Die Variable conn ist einfach die zuvor hergestellte Verbindung zur Datenbank.

Homunculus Reticulli
quelle
Kannst du den Code von posten executeSql(...)? Und auch, hast du wirklich RETURNING *in der SELECTAussage?
van
@van Ich habe das verpasst. Es gibt kein 'RETURNING *' in der SQL, das das Problem verursacht. Ich werde die Frage korrigieren.
Homunculus Reticulli
1
Ist diese Antwort [ stackoverflow.com/questions/3944276/… hilfreich?
van
2
@van: Danke!. ja tut es. Ich musste '\ %%' anstelle von '%' verwenden. Die Anweisung wird jetzt korrekt ausgeführt.
Homunculus Reticulli
3
großartig. Bitte posten Sie eine kurze Antwort (und akzeptieren Sie sie), die der Vollständigkeit halber für Sie funktioniert hat.
van

Antworten:

227

Sie müssen angeben %%, um es zu verwenden, %da es %in Python als Zeichenfolgenformatierung verwendet wird. Wenn Sie also Single schreiben, wird %davon ausgegangen, dass Sie einen Wert durch diesen ersetzen werden.

Wenn Sie also Single %in String mit Abfrage platzieren möchten, platzieren Sie immer Double %.

Nilesh
quelle
27
Ich wünschte, sie würden diese Fehlermeldung aktualisieren. Jedes Mal, wenn ich sie
erhalte, lande
86

SQLAlchemy verfügt über eine text()Funktion zum Umbrechen von Text, die für Sie scheinbar korrekt aus dem SQL-Code ausgeht.

Dh

res = executeSql(sqlalchemy.text(sql))

sollte für Sie arbeiten und Sie vor dem manuellen Entkommen bewahren.

Ilja Everilä
quelle
13
Dies sollte die ausgewählte Antwort sein. Es hat das Problem in meinem Fall gelöst.
Gani Simsek
1
Beachten Sie, dass dies Kommentaren nicht entgeht, ansonsten aber eine fantastische Lösung ist.
ClimbsRocks
Das hat bei mir funktioniert und war einfacher zu implementieren, als alle unsere Abfragen mit double% zu ändern
Philippe Oger
6

Ich kann das "executeSql" in den Dokumenten von sqlalchemy Version 1.2 nicht finden , aber die folgende Zeile hat für mich funktioniert

engine.execute(sqlalchemy.text(sql_query))
Chandra Prakash Dixit
quelle
4

Es scheint, dass Ihr Problem mit diesem Fehler zusammenhängt .

In diesem Fall sollten Sie als Problemumgehung dreimal entkommen.

Brian Cain
quelle
2

Ich habe einen weiteren Fall gefunden, als dieser Fehler auftritt:

c.execute("SELECT * FROM t WHERE a = %s")

Mit anderen Worten, wenn Sie parameter ( %s) in der Abfrage angeben, aber vergessen, Abfrageparameter hinzuzufügen. In diesem Fall ist die Fehlermeldung sehr irreführend.

Tupteq
quelle
1

Noch ein Hinweis: Sie müssen auch %Zeichen in Kommentaren maskieren (oder löschen) . Entgeht leider sqlalchemy.text(query_string)nicht den Prozentzeichen in den Kommentaren.

ClimbsRocks
quelle
1

Eine andere Möglichkeit, Ihr Problem zu lösen , besteht darin, einen regulären Ausdruck zu verwenden , wenn Sie %Zeichen nicht entkommen oder verwenden möchten sqlalchemy.text().

Anstatt:

select id from ref_geog where short_name LIKE '%opt'

Versuchen Sie (für Übereinstimmungen zwischen Groß- und Kleinschreibung):

select id from ref_geog where short_name ~ 'opt$' 

oder (ohne Berücksichtigung der Groß- und Kleinschreibung):

select id from ref_geog where short_name ~* 'opt$'

Sowohl LIKEals auch Regex werden in der Dokumentation zum Mustervergleich behandelt .

Beachten Sie, dass:

Im Gegensatz zu LIKE-Mustern darf ein regulärer Ausdruck an einer beliebigen Stelle innerhalb einer Zeichenfolge übereinstimmen, es sei denn, der reguläre Ausdruck ist explizit am Anfang oder Ende der Zeichenfolge verankert.

Für einen Anker können Sie die Zusicherung $für das Ende der Zeichenfolge (oder ^für den Anfang) verwenden.

C8H10N4O2
quelle
0

Dies könnte auch aus dem Fall resultieren - falls Parameter, die an SQL übergeben werden sollen, im DICT-Format deklariert und in SQL in Form von LIST oder TUPPLE bearbeitet werden.

Pralhad Narsinh Sonar
quelle