Pesan galat SQLAlchemy Aneh: TypeError: objek 'dict' tidak mendukung pengindeksan

145

Saya menggunakan SQL buatan tangan untuk mengambil data dari database PG, menggunakan SqlAlchemy. Saya mencoba kueri yang berisi operator seperti SQL '%' dan yang tampaknya melempar SqlAlcjhemy melalui loop:

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

Adakah yang tahu apa yang menyebabkan pesan kesalahan yang menyesatkan ini dan bagaimana saya dapat memperbaikinya?

[[Sunting]]

Sebelum ada yang bertanya, tidak ada yang istimewa atau mewah tentang fungsi yang disertakan di atas. Sebagai contoh, fungsi executeSql () cukup memanggil conn.execute (sql) dan mengembalikan hasilnya. Sambungan variabel hanyalah koneksi yang sebelumnya dibuat ke database.

Homunculus Reticulli
sumber
dapatkah Anda memposting kode executeSql(...)? Dan juga, apakah Anda benar-benar ada RETURNING *dalam SELECTpernyataan itu?
van
@van, aku merindukan yang itu. Tidak ada 'RETURNING *' di SQL yang menyebabkan masalah. Saya akan memperbaiki pertanyaannya.
Homunculus Reticulli
1
Apakah jawaban ini [ stackoverflow.com/questions/3944276/… bermanfaat?
van
2
@van: Terima kasih !. ya benar. Saya harus menggunakan '\ %%' daripada '%'. Pernyataan itu dijalankan dengan benar sekarang.
Homunculus Reticulli
3
Bagus. tolong kirimkan jawaban singkat (dan terima) yang berfungsi untuk Anda demi kelengkapan.
van

Jawaban:

227

Anda harus memberi %%untuk menggunakannya %karena %dalam python digunakan sebagai pemformatan string sehingga ketika Anda menulis tunggal %asumsikan bahwa Anda akan mengganti beberapa nilai dengan ini.

Jadi, ketika Anda ingin menempatkan tunggal %dalam string dengan kueri allways place double %.

Nilesh
sumber
27
Saya berharap mereka akan memperbarui pesan kesalahan itu, setiap kali saya mendapatkannya saya akhirnya mendarat di halaman ini dan menjawab
oshi2016
86

SQLAlchemy memiliki text()fungsi untuk membungkus teks yang tampaknya lolos dari SQL untuk Anda.

Yaitu

res = executeSql(sqlalchemy.text(sql))

harus bekerja untuk Anda dan menyelamatkan Anda dari keharusan melakukan penyelamatan manual.

Ilja Everilä
sumber
13
Ini harus menjadi jawaban yang dipilih. Itu memecahkan masalah dalam kasus saya.
Gani Simsek
1
Perhatikan bahwa ini tidak luput dari komentar, tetapi sebaliknya merupakan solusi yang fantastis.
ClimbsRocks
Itu berhasil bagi saya, dan lebih mudah diterapkan daripada mengubah semua pertanyaan kami dengan% ganda
Philippe Oger
6

Saya tidak dapat menemukan "executeSql" di sqlalchemy versi 1.2 docs , tetapi baris di bawah ini berfungsi untuk saya

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

Sepertinya masalah Anda mungkin terkait dengan bug ini .

Dalam hal ini, Anda harus melarikan diri tiga kali lipat sebagai solusinya.

Brian Cain
sumber
2

Saya menemukan satu lagi kasus ketika kesalahan ini muncul:

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

Dengan kata lain, jika Anda memberikan parameter ( %s) dalam kueri, tetapi Anda lupa menambahkan params kueri. Dalam hal ini pesan kesalahan sangat menyesatkan.

Tupteq
sumber
1

Satu lagi catatan - Anda harus melarikan diri (atau menghapus) %karakter dalam komentar juga. Sayangnya, sqlalchemy.text(query_string)tidak luput dari tanda persen di komentar.

ClimbsRocks
sumber
1

Cara lain untuk menyelesaikan masalah Anda, jika Anda tidak ingin keluar dari %karakter atau menggunakan sqlalchemy.text(), adalah dengan menggunakan ekspresi reguler.

Dari pada:

select id from ref_geog where short_name LIKE '%opt'

Coba (untuk pencocokan case-sensitive):

select id from ref_geog where short_name ~ 'opt$' 

atau (untuk case-insensitive):

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

Baik LIKEdan regex tercakup dalam dokumentasi tentang pencocokan pola .

Perhatikan bahwa:

Tidak seperti pola LIKE, ekspresi reguler diizinkan untuk mencocokkan di mana saja dalam string, kecuali ekspresi reguler secara eksplisit berlabuh ke awal atau akhir string.

Untuk jangkar, Anda dapat menggunakan pernyataan $untuk akhir string (atau ^untuk awal).

C8H10N4O2
sumber
0

Ini juga bisa dihasilkan dari kasus - dalam hal parameter yang akan diteruskan ke SQL dideklarasikan dalam format DICT dan sedang dimanipulasi dalam SQL dalam bentuk LIST atau TUPPLE.

Pralhad Narsinh Sonar
sumber