Strano messaggio di errore SQLAlchemy: TypeError: l'oggetto 'dict' non supporta l'indicizzazione


145

Sto usando SQL artigianale per recuperare i dati da un database PG, usando SqlAlchemy. Sto provando una query che contiene l'operatore simile a SQL '%' e che sembra lanciare SqlAlcjhemy in un ciclo:

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

Qualcuno sa cosa sta causando questo messaggio di errore fuorviante e come posso risolverlo?

[[Modificare]]

Prima che qualcuno lo chieda, non c'è nulla di speciale o di fantasia nelle funzioni incluse sopra. Ad esempio, la funzione executeSql () richiama semplicemente conn.execute (sql) e restituisce i risultati. La variabile conn è semplicemente la connessione precedentemente stabilita al database.


puoi pubblicare il codice di executeSql(...)? E inoltre, hai davvero RETURNING *nella SELECTdichiarazione?
— van,

@van Ho perso quello. Non c'è "RETURNING *" nell'SQL che causa il problema. Correggerò la domanda.
— Homunculus Reticulli,

1
questa risposta è utile [ stackoverflow.com/questions/3944276/… ?
— van,

2
@van: grazie !. si lo fa. Ho dovuto usare '\ %%' invece di '%'. L'istruzione è ora eseguita correttamente.
— Homunculus Reticulli,

3
grande. si prega di inviare una breve risposta (e accettarla) che ha funzionato per voi per completezza.
— van,

Risposte:


227

Devi dare %%per usarlo come %perché %in Python è usare come formattazione di stringhe, quindi quando scrivi single si %presume che stai per sostituire un valore con questo.

Pertanto, quando si desidera posizionare single %in string con la query, posizionare sempre double %.


27
Vorrei che aggiornassero quel messaggio di errore, ogni volta che lo capisco
— finisco

86

SQLAlchemy ha una text()funzione per avvolgere il testo che sembra sfuggire correttamente all'SQL per te.

ie

res = executeSql(sqlalchemy.text(sql))

dovrebbe funzionare per te e salvarti dal dover fare la fuga manuale.


13
Questa dovrebbe essere la risposta selezionata. Ha risolto il problema nel mio caso.
— Gani Simsek,

1
Nota che questo non sfugge ai commenti, ma per il resto è una soluzione fantastica.
— ClimbsRocks,

Ha funzionato per me ed è stato più facile da implementare che modificare tutte le nostre query con il doppio%
— Philippe Oger,


4

Sembra che il tuo problema possa essere correlato a questo errore .

In tal caso, dovresti evadere tre volte come soluzione alternativa.


2

Ho trovato un altro caso quando compare questo errore:

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

In altre parole, se si fornisce parametro ( %s) nella query, ma si dimentica di aggiungere i parametri della query. In questo caso il messaggio di errore è molto fuorviante.


1

Ancora una nota: è necessario evitare (o eliminare) i %caratteri nei commenti. Sfortunatamente, sqlalchemy.text(query_string)non sfugge ai segni di percentuale nei commenti.


1

Un altro modo di risolvere il tuo problema, se non vuoi sfuggire ai %personaggi o usare sqlalchemy.text(), è usare un'espressione regolare.

Invece di:

select id from ref_geog where short_name LIKE '%opt'

Prova (per la corrispondenza sensibile al maiuscolo / minuscolo):

select id from ref_geog where short_name ~ 'opt$' 

oppure (per la distinzione tra maiuscole e minuscole):

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

Sia LIKEe regex sono trattati nella documentazione sulla corrispondenza dei pattern .

Nota che:

A differenza dei modelli LIKE, un'espressione regolare può corrispondere ovunque all'interno di una stringa, a meno che l'espressione regolare non sia esplicitamente ancorata all'inizio o alla fine della stringa.

Per un'ancora, puoi usare l'asserzione $per la fine della stringa (o ^per l'inizio).


0

Ciò potrebbe anche derivare dal caso: nel caso in cui i parametri da passare a SQL siano dichiarati in formato DICT e vengano manipolati in SQL sotto forma di LIST o TUPPLE.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.