2008-11-03 7 views
65

Comment j'échappe à une chaîne dans la procédure stockée de SQL Server afin qu'elle puisse être utilisée en toute sécurité dans l'expression LIKE.Échapper une chaîne dans SQL Server pour pouvoir l'utiliser en toute sécurité dans l'expression LIKE

Supposons que j'ai une variable NVARCHAR comme ceci:

declare @myString NVARCHAR(100); 

Et je veux l'utiliser dans une expression LIKE:

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

Comment puis-je échapper la chaîne (plus précisément, les caractères sont significatifs à LIKE correspondance de modèle, par exemple % ou ?) dans T-SQL, de sorte qu'il est sûr d'utiliser de cette manière?

Par exemple, avec:

@myString = 'aa%bb' 

Je veux:

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

pour correspondre 'aa%bb', 'caa%bbc' mais pas 'aaxbb' ou 'caaxbb'.

+0

Vous n'avez pas mis votre langage de programmation au –

+0

Son langage de programmation est T-SQL. –

Répondre

81

Pour éviter les caractères spéciaux dans une expression LIKE, vous les préfixez avec un caractère d'échappement. Vous pouvez choisir quel caractère d'échappement utiliser avec le mot-clé ESCAPE. (MSDN Ref)

Par exemple, cela échappe au symbole%, en utilisant \ comme char évasion:

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

Si vous ne savez pas ce que les personnages seront dans votre chaîne, et vous ne voulez pas Traitez-les comme jokers, vous pouvez préfixer tous les caractères génériques avec un char échappement, par exemple:

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

(Notez que vous devez échapper à votre évasion ombles aussi, et assurez-vous que c'est le replace intérieur de sorte que vous n'échappent pas ceux ajoutés de l'autre replace déclarations). Ensuite, vous pouvez utiliser quelque chose comme ceci:

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

Rappelez-vous aussi d'allouer plus d'espace pour votre variable @myString car il deviendra plus avec le remplacement de la chaîne.

+0

Actuellement j'utilise l'approche mentionnée dans http://stackoverflow.com/questions/13861004/escaping-the-escape-character-does-not-work-sql-like-operator Voyez-vous des lacunes avec ce code? – Lijo

+2

@Lijo, c'est bien. Cette réponse fait l'échappement en C# alors que la réponse ci-dessus le fait en SQL car ce n'est pas spécifique à C#. De toute façon, le résultat est le même: échapper tous les caractères spéciaux dans votre chaîne de recherche et utiliser le mot-clé ESCAPE dans votre déclaration LIKE. – Rory

+0

Je pense que vous devez également échapper une seule citation (en la remplaçant par deux guillemets simples, pas par «\»). –

5

Vous spécifiez le caractère d'échappement. Documentation ici:
http://msdn.microsoft.com/en-us/library/ms179859.aspx

+1

Je souhaitais quelque chose qui sait déjà ce qui doit être échappé dans une expression LIKE. –

+0

La réponse vous suggérait de spécifier votre propre caractère d'échappement afin que les caractères "significatifs" ne soient plus significatifs. – Goran

3

Voulez-vous rechercher des chaînes qui incluent un caractère d'échappement? Par exemple vous voulez ceci:

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

Où vous voulez chercher tous les champs avec 10%? Si tel est le cas, vous pouvez utiliser la clause ESCAPE pour spécifier un caractère d'échappement et échapper le caractère générique.

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

J'ai ajouté un exemple de ce que je veux à la question. –

16

Avait un problème similaire (en utilisant NHibernate, donc le mot-clé ESCAPE aurait été très difficile) et résolu en utilisant les caractères de parenthèse.Donc, votre échantillon deviendrait

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

Si vous avez besoin de preuve:

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

Ceci est la meilleure réponse. Ne compte pas sur l'échappement et fonctionne pour toutes les chaînes. – John

+0

Je pense que c'est le plus simple et le plus proche de ce que le demandeur recherchait. Pour ne pas dire que ESCAPE n'est pas aussi utile dans certains cas. – bitoolean

12

Plutôt que d'échapper tous caractères dans une chaîne qui ont une signification particulière dans la syntaxe de modèle étant donné que vous utilisez l'un des principaux caractères génériques dans le modèle, c'est plus rapide et plus facile à faire.

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

Dans le cas où vous n'utilisez pas un caractère générique de premier plan l'approche doit être évitée ci-dessus mais comme il ne peut pas utiliser un index sur YourColumn.

En outre dans les cas où le plan d'exécution optimale varie en fonction du nombre de lignes correspondant à des estimations peuvent être mieux lors de l'utilisation LIKE avec le crochet échappe par rapport à la syntaxe both CHARINDEX et the ESCAPE keyword.

+0

Excellent! Mais que faire s'il n'y avait pas de wild card? – Colin

+1

@Colin - S'il n'y avait pas de caractère générique de premier plan et que le but était d'échapper à ** tous les caractères génériques ailleurs dans la chaîne, vous pouvez simplement utiliser '=' à la place. Les réponses aux caractères spéciaux qui s'échappent peuvent toujours être utiles pour une requête recherchant des valeurs commençant par une valeur particulière, bien que 'LIKE' puisse utiliser un index dans ce cas, mais pas' CHARINDEX'. –

Questions connexes