Garip SQLAlchemy hata mesajı: TypeError: 'dict' nesnesi indekslemeyi desteklemiyor


145

SqlAlchemy kullanarak bir PG veritabanından veri almak için el hazırlanmış SQL kullanıyorum. SQL gibi operatör '%' içeren ve bir döngü aracılığıyla SqlAlcjhemy atmak gibi bir sorgu çalışıyorum:

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

Herhangi biri bu yanıltıcı hata iletisine neyin neden olduğunu ve nasıl düzeltebilir bilir?

[[Düzenle]]

Herhangi biri sormadan önce, yukarıdaki işlevler hakkında özel veya süslü bir şey yoktur. Örneğin executeSql () işlevi conn.execute (sql) işlevini çağırır ve sonuçları döndürür. Conn değişkeni, veritabanına önceden kurulmuş bağlantıdır.


kodunu gönderebilir misin executeSql(...)? Ve ayrıca, eğer gerçekten var mı RETURNING *içinde SELECTdeyimi?
Van

@van bunu kaçırdım. SQL'de soruna neden olan 'GERİ DÖNÜŞ *' yoktur. Soruyu düzeltirim.
Homunculus Reticulli

1
Bu cevap [ stackoverflow.com/questions/3944276/… faydalı mı?
van

2
@van: Teşekkürler !. Evet öyle. '%' Yerine '\ %%' kullanmak zorunda kaldım. İfade şimdi doğru bir şekilde yürütüldü.
Homunculus Reticulli

3
harika. Lütfen size eksiksizlik uğruna işe yarayan kısa bir cevap gönderin (ve kabul edin).
Van

Yanıtlar:


227

Kullanmak için vermelisiniz %%, %çünkü %python'da dize biçimlendirme olarak kullanılır, böylece tek yazdığınızda %, bununla bir değer değiştireceğinizi varsayalım.

Yani %sorgu allway dize tek yerleştirmek istediğinizde çift ​​yerleştirin %.


27
Keşke bu hata mesajını güncellemelerini dilerdim, her aldığımda bu sayfaya inip sonunda cevap
verdim

86

SQLAlchemy, sizin için SQL'den text()doğru şekilde kaçıyor gibi görünen metni kaydırma işlevine sahiptir .

yani

res = executeSql(sqlalchemy.text(sql))

sizin için çalışmalı ve manuel kaçmayı yapmak zorunda kalmamalısınız.


13
Bu seçilen cevap olmalıdır. Benim durumumda sorunu çözdü.
Gani Şimşek

1
Bunun yorumlardan kaçmadığını, ancak aksi takdirde harika bir çözüm olduğunu unutmayın.
ClimbsRocks

Bu benim için çalıştı ve tüm sorularımızı% çift ile değiştirmekten daha kolaydı
Philippe Oger


4

Sorununuz bu hata ile ilgili olabilir .

Bu durumda, geçici çözüm olarak üçlü kaçış yapmanız gerekir.


2

Bu hata ortaya çıktığında bir dava daha buldum:

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

Başka bir deyişle, %ssorguda parametre ( ) sağlarsanız , ancak sorgu parametreleri eklemeyi unutursanız. Bu durumda hata mesajı çok yanıltıcıdır.


1

Bir not daha %- yorumlardaki karakterlerden de kaçmanız (veya silmeniz) gerekir . Ne yazık ki, sqlalchemy.text(query_string)yorumlarda yüzde işaretleri kaçmaz.


1

%Karakterlerden kaçmak veya kullanmak istemiyorsanız sorununuzu çözmenin başka bir yolu da sqlalchemy.text()normal bir ifade kullanmaktır.

Onun yerine:

select id from ref_geog where short_name LIKE '%opt'

Deneyin (büyük / küçük harfe duyarlı eşleşme için):

select id from ref_geog where short_name ~ 'opt$' 

veya (büyük / küçük harfe duyarlı olmayanlar için):

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

Hem LIKEregex hem de desen eşleşmesi ile ilgili belgelerde ele alınmıştır .

Bunu not et:

LIKE desenlerinden farklı olarak, normal ifade dizenin başına veya sonuna açıkça bağlı değilse, normal ifadenin dize içindeki herhangi bir yerde eşleşmesine izin verilir.

Bir çapa $için, ipin sonu (veya ^başlangıç ​​için) iddiasını kullanabilirsiniz .


0

Bu durum, SQL'e iletilecek parametrelerin DICT formatında bildirilmesi ve SQL'de LIST veya TUPPLE şeklinde manipüle edilmesi durumunda da olabilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.