Vâng, đây là một mớ hỗn độn thực sự. Cả MySQL và PostgreSQL đều sử dụng dấu gạch chéo ngược thoát cho việc này theo mặc định. Đây là một nỗi đau khủng khiếp nếu bạn cũng thoát chuỗi một lần nữa bằng dấu gạch chéo ngược thay vì sử dụng tham số và nó cũng không chính xác theo ANSI SQL:1992, cho biết theo mặc định không có ký tự thoát bổ sung nào trên đầu thoát chuỗi bình thường và do đó không có cách nào để bao gồm một chữ %
hoặc _
.
Tôi cho rằng phương pháp thay thế dấu gạch chéo ngược đơn giản cũng bị lỗi nếu bạn tắt các thoát dấu gạch chéo ngược (bản thân chúng không tuân thủ ANSI SQL) bằng cách sử dụng NO_BACKSLASH_ESCAPE
sql_mode trong MySQL hoặc standard_conforming_strings
tâm sự trong PostgreSQL (mà các nhà phát triển PostgreSQL đã đe dọa làm cho một vài phiên bản bây giờ).
Giải pháp thực sự duy nhất là sử dụng LIKE...ESCAPE
ít được biết đến cú pháp để chỉ định một ký tự thoát rõ ràng cho LIKE
-họa tiết. Điều này được sử dụng thay vì thoát dấu gạch chéo ngược trong MySQL và PostgreSQL, làm cho chúng phù hợp với những gì mọi người khác làm và cung cấp một cách đảm bảo để bao gồm các ký tự nằm ngoài dải. Ví dụ với =
ký tên như một lối thoát:
# look for term anywhere within title
term= term.replace('=', '==').replace('%', '=%').replace('_', '=_')
sql= "SELECT * FROM things WHERE description LIKE %(like)s ESCAPE '='"
cursor.execute(sql, dict(like= '%'+term+'%'))
Điều này hoạt động trên cơ sở dữ liệu tương thích với PostgreSQL, MySQL và ANSI SQL (tất nhiên là mô-đun theo kiểu mô-đun thay đổi trên các mô-đun db khác nhau).
Có thể vẫn còn sự cố với MS SQL Server / Sybase, điều này dường như cũng cho phép [a-z]
nhóm ký tự kiểu trong LIKE
biểu thức. Trong trường hợp này, bạn cũng muốn thoát khỏi chữ [
ký tự với .replace('[', '=[')
. Tuy nhiên theo ANSI SQL thoát một ký tự không cần thoát là không hợp lệ! (Argh!) Vì vậy, mặc dù nó có thể vẫn hoạt động trên các DBMS thực, nhưng bạn vẫn không tuân thủ ANSI. thở dài ...