Thông báo lỗi SQLAlchemy lạ: Đối tượng TypeError: 'dict' không hỗ trợ lập chỉ mục


145

Tôi đang sử dụng SQL thủ công để tìm nạp dữ liệu từ cơ sở dữ liệu PG, sử dụng SqlAlchemy. Tôi đang thử một truy vấn có chứa toán tử như SQL '%' và điều đó dường như ném SqlAlcjhemy qua một vòng lặp:

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

Có ai biết điều gì gây ra thông báo lỗi sai này không và làm cách nào để khắc phục?

[[Biên tập]]

Trước khi có ai hỏi, không có gì đặc biệt hay lạ mắt về các chức năng bao gồm ở trên. Ví dụ, hàm execSql () chỉ đơn giản gọi hàm Conn.execute (sql) và trả về kết quả. Kết nối biến chỉ đơn giản là kết nối được thiết lập trước đó đến cơ sở dữ liệu.


bạn có thể gửi mã của executeSql(...)? Và ngoài ra, bạn có thực sự có RETURNING *trong SELECTtuyên bố?
van

@van Tôi nhớ cái đó. Không có 'RETURNING *' trong SQL gây ra sự cố. Tôi sẽ sửa câu hỏi.
Homunculus Reticulli

1
câu trả lời này [ stackoverflow.com/questions/3944276/ có hữu ích không?
van

2
@van: Cảm ơn!. đúng vậy Tôi đã phải sử dụng '\ %%' thay vì '%'. Tuyên bố được thực hiện chính xác ngay bây giờ.
Homunculus Reticulli

3
tuyệt quá. xin vui lòng gửi một câu trả lời ngắn (và chấp nhận nó) mà làm việc cho bạn vì sự hoàn chỉnh.
van

Câu trả lời:


227

Bạn phải đưa ra %%để sử dụng nó %%trong python được sử dụng như định dạng chuỗi, vì vậy khi bạn viết đơn, %giả sử rằng bạn sẽ thay thế một số giá trị bằng giá trị này.

Vì vậy, khi bạn muốn đặt một %chuỗi trong chuỗi với truy vấn luôn đặt gấp đôi %.


27
Tôi ước họ sẽ cập nhật thông báo lỗi đó, mỗi khi tôi nhận được nó, tôi sẽ hạ cánh trên trang này và trả lời
oshi2016

86

SQLAlchemy có text()chức năng gói văn bản dường như thoát chính xác SQL cho bạn.

I E

res = executeSql(sqlalchemy.text(sql))

nên làm việc cho bạn và cứu bạn khỏi phải làm thủ công thoát.


13
Đây phải là câu trả lời được lựa chọn. Nó giải quyết vấn đề trong trường hợp của tôi.
Gani Simsek

1
Lưu ý rằng điều này không thoát khỏi các bình luận, nhưng nếu không thì là một giải pháp tuyệt vời.
ClimbsRocks

Điều đó hiệu quả với tôi và dễ thực hiện hơn là thay đổi tất cả các truy vấn của chúng tôi với %%
Philippe Oger


4

Có vẻ như vấn đề của bạn có thể liên quan đến lỗi này .

Trong trường hợp đó, bạn nên thoát ba lần như một cách giải quyết.


2

Tôi tìm thấy một trường hợp nữa khi lỗi này xuất hiện:

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

Nói cách khác, nếu bạn cung cấp tham số ( %s) trong truy vấn, nhưng bạn quên thêm tham số truy vấn. Trong trường hợp này thông báo lỗi là rất sai lệch.


1

Thêm một lưu ý nữa - bạn cũng phải thoát (hoặc xóa) các %ký tự trong các bình luận. Thật không may, sqlalchemy.text(query_string)không thoát khỏi các dấu hiệu phần trăm trong các ý kiến.


1

Một cách khác để giải quyết vấn đề của bạn, nếu bạn không muốn thoát %ký tự hoặc sử dụng sqlalchemy.text(), là sử dụng biểu thức chính quy.

Thay vì:

select id from ref_geog where short_name LIKE '%opt'

Hãy thử (đối với trường hợp phân biệt chữ hoa chữ thường):

select id from ref_geog where short_name ~ 'opt$' 

hoặc (đối với trường hợp không nhạy cảm):

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

Cả hai LIKEvà regex đều được đề cập trong tài liệu về khớp mẫu .

Lưu ý rằng:

Không giống như các mẫu THÍCH, một biểu thức chính quy được phép khớp bất kỳ vị trí nào trong một chuỗi, trừ khi biểu thức chính quy được neo rõ ràng vào đầu hoặc cuối của chuỗi.

Đối với một neo, bạn có thể sử dụng xác nhận $cho cuối chuỗi (hoặc ^để bắt đầu).


0

Điều này cũng có thể xảy ra từ trường hợp - trong trường hợp các tham số được truyền vào SQL được khai báo dưới dạng DICT và đang được thao tác trong SQL dưới dạng LIST hoặc TUPPLE.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.