L'opérateur LIKE est-il sensible à la casse avec MSSQL Server?

99

Dans la documentation sur l'opérateur LIKE , rien n'est dit sur sa sensibilité à la casse. C'est ça? Comment l'activer / le désactiver?

J'interroge des varchar(n)colonnes, sur une installation de Microsoft SQL Server 2005, si cela compte.

Marcel
la source
14
Cela dépend du classement de votre colonne (ou base de données). Si elle est sensible à la casse, elle LIKEest sensible à la casse, si ce n'est pas le cas, alors LIKEne l'est pas
Lamak
Consultez la documentation sur les classements SQL-Server msdn.microsoft.com/en-us/library/ms144250%28v=sql.105%29.aspx
GarethD
Quel est ton but? Voulez-vous qu'il soit sensible à la casse ou non à la casse?
Aaron Bertrand
1
La sensibilité à la casse est par défaut le classement de la colonne qui est par défaut celui de la base de données. Il est généralement arrondi, dans quelle direction voulez-vous aller?
Tony Hopkinson

Réponses:

101

Ce n'est pas l'opérateur qui est sensible à la casse, c'est la colonne elle-même.

Lorsqu'une installation SQL Server est effectuée, un classement par défaut est choisi pour l'instance. Sauf indication contraire explicite (vérifiez la clause collate ci-dessous) lorsqu'une nouvelle base de données est créée, elle hérite du classement de l'instance et lorsqu'une nouvelle colonne est créée, elle hérite du classement de la base de données à laquelle elle appartient.

Un classement comme sql_latin1_general_cp1_ci_asdicte la façon dont le contenu de la colonne doit être traité. CI signifie insensible à la casse et AS signifie sensible aux accents.

Une liste complète des classements est disponible à l' adresse https://msdn.microsoft.com/en-us/library/ms144250(v=sql.105).aspx

(a) Pour vérifier un classement d'instances

select serverproperty('collation')

(b) Pour vérifier un classement de base de données

select databasepropertyex('databasename', 'collation') sqlcollation

(c) Pour créer une base de données en utilisant un classement différent

create database exampledatabase
collate sql_latin1_general_cp1_cs_as 

(d) Pour créer une colonne en utilisant un classement différent

create table exampletable (
    examplecolumn varchar(10) collate sql_latin1_general_cp1_ci_as null
)

(e) Pour modifier un classement de colonnes

alter table exampletable
alter column examplecolumn varchar(10) collate sql_latin1_general_cp1_ci_as null

Il est possible de modifier une instance et des classements de base de données, mais cela n'affecte pas les objets créés précédemment.

Il est également possible de modifier un classement de colonnes à la volée pour la comparaison de chaînes, mais cela est fortement déconseillé dans un environnement de production car cela est extrêmement coûteux.

select
  column1 collate sql_latin1_general_cp1_ci_as as column1
from table1
lolol
la source
5
Il semble que la gamme de caractères comme [A-Z]est toujours insensible à la casse. [ABCDEFGHIJKLMNOPQRSŠTUVWXYZŽÅÄÖ]semble cependant obéir à la collation.
jumxozizi
1
En outre, vous pouvez interroger la sensibilité à la casse d'une colonne particulière avec quelque chose comme ceci:select COLLATION_NAME, iif(cast(COLLATIONPROPERTY(COLLATION_NAME, 'ComparisonStyle') as int) & 1 = 0, 'case sensitive', 'case insensitive') from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'exampletable' and COLUMN_NAME = 'examplecolumn'
Jeppe Stig Nielsen
@jumxozizi J'ai ajouté votre suggestion à la réponse.
John Zabroski
@JeppeStigNielsen J'ai ajouté votre suggestion à la réponse.
John Zabroski
18

Tous ces discours sur le classement semblent un peu trop compliqués. Pourquoi ne pas simplement utiliser quelque chose comme:

IF UPPER(@@VERSION) NOT LIKE '%AZURE%'

Alors votre chèque est insensible à la casse quel que soit le classement

Phil R
la source
10
Parce que ce n'est pas discutable. Votre exemple utilise une variable et un caractère générique en tête. Mais contre une colonne indexée avec un classement insensible à la casse like 'a%'pourrait utiliser l'index et la upperversion ne le pouvait pas.
Martin Smith
3
La question était de savoir si l' likeopérateur est sensible à la casse ou non .
jumxozizi
Vous devez connaître le classement, sinon cela pourrait être inutile. Par exemple, si la colonne interrogée utilise Latin1_General_CI_AS, alors faire UPPER(@@VALUE) NOT LIKE '%SOMETHING%'ou @@COLUMN NOT LIKE '%SOMETHING%'n'est pas pertinent: le résultat serait le même.
rsenna
13

Vous avez la possibilité de définir l' ordre de classement au moment de la définition de votre table. Si vous définissez un ordre sensible à la casse, votre LIKEopérateur se comportera de manière sensible à la casse; si vous définissez un ordre de classement insensible à la casse, l' LIKEopérateur ignorera également la casse des caractères:

CREATE TABLE Test (
    CI_Str VARCHAR(15) COLLATE Latin1_General_CI_AS -- Case-insensitive
,   CS_Str VARCHAR(15) COLLATE Latin1_General_CS_AS -- Case-sensitive
);

Voici une démo rapide sur sqlfiddle montrant les résultats de l'ordre de classement sur les recherches avec LIKE.

dasblinkenlight
la source
12

Si vous souhaitez effectuer une recherche sensible à la casse sans changer le classement de la colonne / base de données / serveur, vous pouvez toujours utiliser la COLLATEclause, par exemple

USE tempdb;
GO
CREATE TABLE dbo.foo(bar VARCHAR(32) COLLATE Latin1_General_CS_AS);
GO
INSERT dbo.foo VALUES('John'),('john');
GO
SELECT bar FROM dbo.foo 
  WHERE bar LIKE 'j%';
-- 1 row

SELECT bar FROM dbo.foo 
  WHERE bar COLLATE Latin1_General_CI_AS LIKE 'j%';
-- 2 rows

GO    
DROP TABLE dbo.foo;

Fonctionne également dans l'autre sens, si votre colonne / base de données / serveur est sensible à la casse et que vous ne voulez pas une recherche sensible à la casse, par exemple

USE tempdb;
GO
CREATE TABLE dbo.foo(bar VARCHAR(32) COLLATE Latin1_General_CI_AS);
GO
INSERT dbo.foo VALUES('John'),('john');
GO
SELECT bar FROM dbo.foo 
  WHERE bar LIKE 'j%';
-- 2 rows

SELECT bar FROM dbo.foo 
  WHERE bar COLLATE Latin1_General_CS_AS LIKE 'j%';
-- 1 row

GO
DROP TABLE dbo.foo;
Aaron Bertrand
la source
Méfiez-vous dans la dernière requête si vous l'utilisez, WHERE bar COLLATE Latin1_General_CS_AS LIKE '[j-k]%'elle retournera Johncar dans ce classement, les majuscules Jse trouvent entre minuscules jet minuscules k. C'est comme aAbBcC...jJkKlLmM...ce qui n'est pas évident. Cela semble Latin1_General_BINplus prévisible avec les recherches par plage avec l'opérateur LIKE.
wqw
7

L' likeopérateur prend deux chaînes. Ces chaînes doivent avoir des classements compatibles, ce qui est expliqué ici .

À mon avis, les choses se compliquent alors. La requête suivante renvoie une erreur indiquant que les classements sont incompatibles:

select *
from INFORMATION_SCHEMA.TABLES
where 'abc' COLLATE SQL_Latin1_General_CP1_CI_AS like 'ABC' COLLATE SQL_Latin1_General_CP1_CS_AS

Sur une machine aléatoire ici, le classement par défaut est SQL_Latin1_General_CP1_CI_AS. La requête suivante réussit, mais ne renvoie aucune ligne:

select *
from INFORMATION_SCHEMA.TABLES
where 'abc' like 'ABC' COLLATE SQL_Latin1_General_CP1_CS_AS

Les valeurs "abc" et "ABC" ne correspondent pas dans un monde sensible à la casse.

En d'autres termes, il y a une différence entre ne pas avoir de classement et utiliser le classement par défaut. Lorsqu'un côté n'a pas de classement, alors il est "assigné" un classement explicite de l'autre côté.

(Les résultats sont les mêmes lorsque le classement explicite est à gauche.)

Gordon Linoff
la source
Pouvez-vous reproduire l'erreur sur une table qui n'est PAS un objet système comme INFORMATION_SCHEMA.TABLES?
Aaron Bertrand
@AaronBertrand. . . Oui je peux. La base de données est-elle cassée;)?
Gordon Linoff
Je ne sais pas, je suis actuellement sur un appareil mobile et je ne peux pas faire tourner une machine virtuelle Windows. Je ne sais tout simplement pas si toute votre description est techniquement exacte.
Aaron Bertrand
4

Essayez de courir,

SELECT SERVERPROPERTY('COLLATION')

Vérifiez ensuite si votre classement est sensible à la casse ou non.

RandomUs1r
la source
1

Vous pouvez modifier la propriété de chaque élément.

sensible aux majuscules et minuscules

Daniel Cadena
la source
0

Vous pouvez facilement modifier le classement dans Microsoft SQL Server Management Studio.

  • table de clic droit -> conception.
  • choisissez votre colonne, faites défiler les propriétés de la colonne i vers le classement.
  • Définissez vos préférences de tri en cochant "Case Sensitive"
Anders Finn Jørgensen
la source