2008-11-03 24 views
65

Làm cách nào để thoát chuỗi trong quy trình được lưu trữ của SQL Server sao cho an toàn để sử dụng trong biểu thức LIKE.Thoát chuỗi trong SQL Server để an toàn để sử dụng trong biểu thức LIKE

Giả sử tôi có một biến NVARCHAR như vậy:

declare @myString NVARCHAR(100); 

Và tôi muốn sử dụng nó trong một biểu thức LIKE:

... WHERE ... LIKE '%' + @myString + '%'; 

Làm thế nào để thoát khỏi chuỗi (cụ thể hơn, nhân vật mà có ý nghĩa đối với việc kết hợp mẫu LIKE, ví dụ: % hoặc ?) trong T-SQL, để an toàn để sử dụng theo cách này?

Ví dụ, đưa ra:

@myString = 'aa%bb' 

Tôi muốn:

WHERE ... LIKE '%' + @somehowEscapedMyString + '%' 

để phù hợp với 'aa%bb', 'caa%bbc' nhưng không 'aaxbb' hoặc 'caaxbb'.

+0

Bạn chưa đặt ngôn ngữ lập trình của mình ở –

+0

Ngôn ngữ lập trình của anh ấy là T-SQL. –

Trả lời

81

Để thoát các ký tự đặc biệt trong biểu thức LIKE, bạn đặt trước chúng với ký tự thoát. Bạn có thể chọn char thoát nào để sử dụng với từ khóa ESCAPE. (MSDN Ref)

Ví dụ này thoát biểu tượng%, sử dụng \ như char thoát:

select * from table where myfield like '%15\% off%' ESCAPE '\' 

Nếu bạn không biết những gì các nhân vật sẽ được trong chuỗi của bạn, và bạn không muốn đối xử với họ như ký tự đại diện, bạn có thể thêm tiền tố tất cả các ký tự đại diện với một char thoát, ví dụ:

set @myString = replace( 
       replace( 
       replace( 
       replace(@myString 
       , '\', '\\') 
       , '%', '\%') 
       , '_', '\_') 
       , '[', '\[') 

(Lưu ý rằng bạn cần phải thoát ra thoát char của bạn quá, và chắc chắn rằng đó là khu vực nội replace do đó bạn không thoát những cái được thêm vào từkhácbáo cáo). Sau đó, bạn có thể sử dụng một cái gì đó như thế này:

select * from table where myfield like '%' + @myString + '%' ESCAPE '\' 

Cũng nhớ phân bổ nhiều không gian hơn cho biến @myString của bạn vì nó sẽ trở nên dài hơn với chuỗi thay thế.

+0

Hiện tại tôi đang sử dụng cách tiếp cận được đề cập trong http://stackoverflow.com/questions/13861004/escaping-the-escape-character-does-not-work-sql-like-operator Bạn có thấy bất kỳ thiếu sót nào với mã đó không? – Lijo

+2

@Lijo, được rồi. Câu trả lời đó thực hiện thoát trong C# trong khi câu trả lời ở trên thực hiện nó trong SQL vì nó không phải là C# -specific. Dù bằng cách nào thì kết quả cũng giống nhau: thoát khỏi các ký tự đặc biệt trong chuỗi tìm kiếm của bạn và sử dụng từ khóa ESCAPE trong câu lệnh LIKE của bạn. – Rory

+0

Tôi nghĩ rằng bạn cũng cần phải thoát khỏi một trích dẫn duy nhất (thay thế nó bằng hai dấu nháy đơn, không phải với '\ ''). –

5

Bạn chỉ định ký tự thoát. Tài liệu tại đây:
http://msdn.microsoft.com/en-us/library/ms179859.aspx

+1

Tôi đã mong muốn một cái gì đó đã nows những gì cần phải được thoát trong một biểu thức LIKE. –

+0

Câu trả lời gợi ý bạn chỉ định nhân vật thoát của riêng bạn để các ký tự "có ý nghĩa" sẽ không còn ý nghĩa nữa. – Goran

3

Bạn có muốn tìm các chuỗi có ký tự thoát không? Ví dụ: bạn muốn điều này:

select * from table where myfield like '%10%%'. 

Nơi bạn muốn tìm kiếm tất cả các trường có 10%? Nếu đó là trường hợp thì bạn có thể sử dụng mệnh đề ESCAPE để chỉ định một ký tự thoát và thoát khỏi ký tự đại diện.

select * from table where myfield like '%10!%%' ESCAPE '!' 
+0

Tôi đã thêm một ví dụ về những gì tôi muốn cho câu hỏi. –

16

Đã xảy ra sự cố tương tự (sử dụng NHibernate, vì vậy từ khóa ESCAPE sẽ rất khó) và giải quyết nó bằng cách sử dụng các ký tự trong ngoặc đơn.Vì vậy, mẫu của bạn sẽ trở thành

WHERE ... LIKE '%aa[%]bb%' 

Nếu bạn cần bằng chứng:

create table test (field nvarchar(100)) 
go 
insert test values ('abcdef%hijklm') 
insert test values ('abcdefghijklm') 
go 
select * from test where field like 'abcdef[%]hijklm' 
go 
+0

Đây là câu trả lời hay nhất. Không dựa vào lối thoát và hoạt động cho tất cả các chuỗi. – John

+0

Tôi nghĩ đây là cách đơn giản nhất và gần gũi nhất với những gì người hỏi đang tìm kiếm. Không phải để nói rằng ESCAPE không hữu ích trong một số trường hợp. – bitoolean

12

Thay vì thoát tất cả ký tự trong một chuỗi mà có ý nghĩa đặc biệt trong cú pháp mẫu cho rằng bạn đang sử dụng một ký tự đại diện hàng đầu trong mô hình nó nhanh hơn và dễ dàng hơn để làm.

SELECT * 
FROM YourTable 
WHERE CHARINDEX(@myString , YourColumn) > 0 

Tuy nhiên, trong trường hợp bạn không sử dụng ký tự đại diện dẫn đầu thì nên tránh sử dụng chỉ mục trên YourColumn. Ngoài ra trong trường hợp kế hoạch thực hiện tối ưu sẽ thay đổi tùy theo số lượng hàng phù hợp, ước tính có thể tốt hơn khi sử dụng LIKE với cú pháp thoát khung vuông khi so sánh với both CHARINDEXthe ESCAPE keyword.

+0

Tuyệt vời! Nhưng nếu không có thẻ hoang dã hàng đầu thì sao? – Colin

+1

@Colin - Nếu không có ký tự đại diện hàng đầu và mục đích là để thoát ** tất cả ** ký tự đại diện thẻ ở nơi khác trong chuỗi thì bạn chỉ có thể sử dụng '=' thay thế. Các câu trả lời ký tự đặc biệt có thể vẫn hữu ích cho truy vấn tìm kiếm các giá trị bắt đầu bằng một giá trị cụ thể mặc dù 'LIKE' có thể sử dụng chỉ mục trong trường hợp đó nhưng' CHARINDEX' không thể. –

Các vấn đề liên quan