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.