ข้อความแสดงข้อผิดพลาด SQLAlchemy แปลก ๆ : TypeError: วัตถุ 'dict' ไม่รองรับการทำดัชนี


145

ฉันใช้ SQL ที่สร้างขึ้นด้วยมือเพื่อดึงข้อมูลจากฐานข้อมูล PG โดยใช้ SqlAlchemy ฉันพยายามค้นหาที่มี SQL เช่นผู้ประกอบการ '%' และที่ดูเหมือนว่าจะโยน SqlAlcjhemy ผ่านวง:

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

มีใครรู้ว่าอะไรทำให้เกิดข้อผิดพลาดที่ทำให้เข้าใจผิดและฉันจะแก้ไขได้อย่างไร

[[แก้ไข]]

ก่อนที่จะมีใครถามไม่มีอะไรพิเศษหรือแฟนซีเกี่ยวกับฟังก์ชั่นด้านบน ตัวอย่างเช่นฟังก์ชั่น executeSql () เพียงแค่เรียก conn.execute (sql) และส่งกลับผลลัพธ์ ตัวแปร conn เป็นเพียงการเชื่อมต่อที่สร้างไว้ก่อนหน้านี้กับฐานข้อมูล


คุณสามารถโพสต์รหัสได้executeSql(...)หรือไม่ และคุณมีจริง ๆRETURNING *ในSELECTคำสั่งหรือไม่
van

@ วานฉันคิดถึงสิ่งนั้น ไม่มี 'RETURNING *' ใน SQL ที่เป็นสาเหตุของปัญหา ฉันจะแก้ไขคำถาม
Homunculus Reticulli

1
คำตอบนี้ [ stackoverflow.com/questions/3944276/…เป็นประโยชน์หรือไม่
van

2
@ วาน: ขอบคุณ! ใช่แล้ว. ฉันต้องใช้ '\ %%' แทนที่จะเป็น '%' คำสั่งถูกดำเนินการอย่างถูกต้องในขณะนี้
Homunculus Reticulli

3
ยิ่งใหญ่ โปรดโพสต์คำตอบสั้น ๆ (และยอมรับ) ที่ใช้งานได้กับคุณเพื่อความสมบูรณ์
van

คำตอบ:


227

คุณต้องให้%%มันใช้%เพราะ%ในไพ ธ อนใช้เป็นการจัดรูปแบบสตริงดังนั้นเมื่อคุณเขียนเดี่ยว%มันจะถือว่าคุณจะแทนที่ค่าบางส่วนด้วยสิ่งนี้

ดังนั้นเมื่อคุณต้องการที่จะวางเดียว%ในสตริงกับ allways %แบบสอบถามวางคู่


27
ฉันหวังว่าพวกเขาจะอัปเดตข้อความแสดงข้อผิดพลาดทุกครั้งที่ฉันรับมันฉันจะลงจอดในหน้านี้และตอบคำถาม
oshi2016

86

SQLAlchemy มีtext()ฟังก์ชั่นสำหรับตัดข้อความที่ดูเหมือนว่าจะหลบหนี SQL อย่างถูกต้องสำหรับคุณ

กล่าวคือ

res = executeSql(sqlalchemy.text(sql))

ควรทำงานให้คุณและช่วยให้คุณไม่ต้องทำคู่มือหลบหนี


13
นี่ควรเป็นคำตอบที่เลือก มันแก้ไขปัญหาในกรณีของฉัน
Gani Simsek

1
โปรดทราบว่านี่ไม่ได้เป็นการหลบหนีความคิดเห็น แต่เป็นวิธีแก้ปัญหาที่ยอดเยี่ยม
ClimbsRocks

ที่ได้ผลสำหรับฉันและง่ายต่อการใช้งานมากกว่าการเปลี่ยนการค้นหาทั้งหมดของเราด้วย double%
Philippe Oger



2

ฉันพบอีกหนึ่งกรณีเมื่อข้อผิดพลาดนี้ปรากฏขึ้น:

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

กล่าวอีกนัยหนึ่งถ้าคุณระบุพารามิเตอร์ ( %s) ในแบบสอบถาม แต่คุณลืมที่จะเพิ่มพารามิเตอร์แบบสอบถาม ในกรณีที่ข้อความผิดพลาดนี้ทำให้เข้าใจผิดมาก


1

อีกหนึ่งข้อความ - คุณต้องหลีกเลี่ยง (หรือลบ) %อักขระในความคิดเห็นด้วย แต่น่าเสียดายที่sqlalchemy.text(query_string)ไม่ได้หลบหนีสัญญาณร้อยละในความคิดเห็น


1

อีกวิธีหนึ่งในการแก้ปัญหาของคุณหากคุณไม่ต้องการหลบหนีจาก%ตัวละครหรือใช้sqlalchemy.text()คือการใช้นิพจน์ทั่วไป

แทน:

select id from ref_geog where short_name LIKE '%opt'

ลอง (เพื่อให้ตรงกับตัวพิมพ์ใหญ่ - เล็ก):

select id from ref_geog where short_name ~ 'opt$' 

หรือ (สำหรับตัวพิมพ์เล็กและตัวพิมพ์ใหญ่):

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

ทั้งสองLIKEและ regex ได้รับความคุ้มครองในเอกสารเกี่ยวกับการจับคู่แบบ

โปรดทราบว่า:

ไม่เหมือนกับรูปแบบ LIKE นิพจน์ทั่วไปจะได้รับอนุญาตให้จับคู่กับที่ใดก็ได้ภายในสตริงยกเว้นว่านิพจน์ทั่วไปจะยึดกับจุดเริ่มต้นหรือจุดสิ้นสุดของสตริงอย่างชัดเจน

สำหรับจุดยึดคุณสามารถใช้การยืนยัน$สำหรับจุดสิ้นสุดของสตริง (หรือ^สำหรับการเริ่มต้น)


0

นี่อาจเป็นผลมาจาก case - ในกรณีที่พารามิเตอร์ที่จะส่งผ่านไปยัง SQL นั้นถูกประกาศในรูปแบบ DICT และกำลังถูกจัดการใน SQL ในรูปแบบของ LIST หรือ TUPPLE

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.