转义 SQLServer 中的字符串,以便在 LIKE 表达式中使用该字符串是安全的

如何转义 SQLServer 存储过程中的字符串,以便在 LIKE表达式中使用它是安全的。

假设我有这样一个 NVARCHAR变量:

declare @myString NVARCHAR(100);

我想把它用在 LIKE表达式中:

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

如何在 T-SQL 中转义字符串(更具体地说,是对 LIKE模式匹配有意义的字符,例如 %?) ,以便以这种方式使用是安全的?

例如:

@myString = 'aa%bb'

我想要:

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

'aa%bb''caa%bbc'匹配,但与 'aaxbb''caaxbb'不匹配。

206884 次浏览

You specify the escape character. Documentation here:
http://msdn.microsoft.com/en-us/library/ms179859.aspx

Do you want to look for strings that include an escape character? For instance you want this:

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

Where you want to search for all fields with 10%? If that is the case then you may use the ESCAPE clause to specify an escape character and escape the wildcard character.

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

To escape special characters in a LIKE expression you prefix them with an escape character. You get to choose which escape char to use with the ESCAPE keyword. (MSDN Ref)

For example this escapes the % symbol, using \ as the escape char:

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

If you don't know what characters will be in your string, and you don't want to treat them as wildcards, you can prefix all wildcard characters with an escape char, eg:

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

(Note that you have to escape your escape char too, and make sure that's the inner replace so you don't escape the ones added from the other replace statements). Then you can use something like this:

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

Also remember to allocate more space for your @myString variable as it will become longer with the string replacement.

Had a similar problem (using NHibernate, so the ESCAPE keyword would have been very difficult) and solved it using the bracket characters. So your sample would become

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

If you need proof:

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

Rather than escaping all characters in a string that have particular significance in the pattern syntax given that you are using a leading wildcard in the pattern it is quicker and easier just to do.

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

In cases where you are not using a leading wildcard the approach above should be avoided however as it cannot use an index on YourColumn.

Additionally in cases where the optimum execution plan will vary according to the number of matching rows the estimates may be better when using LIKE with the square bracket escaping syntax when compared to both CHARINDEX and the ESCAPE keyword.

Alternative escaping syntax:

LIKE Wildcard Literals

The JDBC driver supports the {escape 'escape character'} syntax for using LIKE clause wildcards as literals.

SELECT *
FROM tab
WHERE col LIKE 'a\_c' {escape '\'};

db<>fiddle demo