it-swarm.com.de

Strange SQLAlchemy-Fehlermeldung: TypeError: 'Dict'-Objekt unterstützt keine Indizierung

Ich verwende handgefertigtes SQL zum Abrufen von Daten aus einer PG-Datenbank mithilfe von SqlAlchemy. Ich versuche eine Abfrage, die den SQL-ähnlichen Operator '%' enthält und die 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 an den oben genannten Funktionen nichts Besonderes oder Lustiges. 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.

85

Sie müssen %% angeben, um es als % zu verwenden, da % in Python als String-Formatierung verwendet wird. Wenn Sie also einen einzelnen % schreiben, wird davon ausgegangen, dass Sie einige Werte durch diese Zeichen ersetzen.

Wenn Sie also einen einzelnen % in eine Zeichenfolge mit Abfrage einfügen möchten, platzieren Sie den doppelten %

145
Nilesh

SQLAlchemy verfügt über eine text() - Funktion zum Umschließen von Text, der die SQL für Sie richtig zu umgehen scheint. 

Das heißt.

res = executeSql(sqlalchemy.text(sql))

sollte für Sie arbeiten und Sie von der manuellen Flucht ersparen.

50
user795753

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

In diesem Fall sollten Sie als Problemumgehung eine dreifache Flucht durchführen.

5
Brian Cain

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

engine.execute(sqlalchemy.text(sql_query))

Ein weiterer Hinweis - Sie müssen auch %-Zeichen in Kommentaren mit Escapezeichen versehen (oder löschen). Leider entgeht sqlalchemy.text(query_string) den Prozentzeichen in den Kommentaren nicht. 

1
ClimbsRocks

Ich habe einen weiteren Fall gefunden, wenn dieser Fehler angezeigt wird:

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

Das heißt, wenn Sie den Parameter (%s) in der Abfrage angeben, vergessen Sie jedoch, Abfrageparameter hinzuzufügen. In diesem Fall ist die Fehlermeldung sehr irreführend.

1
Tupteq

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

Anstatt:

select id from ref_geog where short_name LIKE '%opt'

Versuchen Sie (für Übereinstimmung mit Groß- und Kleinschreibung):

select id from ref_geog where short_name ~ 'opt$' 

oder (bei Groß-/Kleinschreibung):

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

Sowohl LIKE als 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 in 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.

0
C8H10N4O2

Dies kann auch aus dem Fall resultieren, dass Parameter, die an die SQL übergeben werden sollen, im DICT-Format deklariert sind und in der SQL in Form von LIST oder TUPPLE bearbeitet werden.