Comment puis-je construire une requête SQL (MS SQL Server) dans laquelle la clause «where» est insensible à la casse?
SELECT * FROM myTable WHERE myField = 'sOmeVal'
Je veux que les résultats reviennent en ignorant le cas
Comment puis-je construire une requête SQL (MS SQL Server) dans laquelle la clause «where» est insensible à la casse?
SELECT * FROM myTable WHERE myField = 'sOmeVal'
Je veux que les résultats reviennent en ignorant le cas
Réponses:
Dans la configuration par défaut d'une base de données SQL Server, les comparaisons de chaînes ne sont pas sensibles à la casse. Si votre base de données remplace ce paramètre (via l'utilisation d'un autre classement), vous devrez spécifier le type de classement à utiliser dans votre requête.
SELECT * FROM myTable WHERE myField = 'sOmeVal' COLLATE SQL_Latin1_General_CP1_CI_AS
Notez que le classement que j'ai fourni n'est qu'un exemple (bien qu'il fonctionnera très probablement très bien pour vous). Un aperçu plus détaillé des classements SQL Server peut être trouvé ici .
UPPER
ou en LOWER
cas, puis en utilisant la LIKE
recherche?
En règle générale, les comparaisons de chaînes ne sont pas sensibles à la casse. Si votre base de données est configurée pour un classement sensible à la casse, vous devez forcer à utiliser un classement insensible à la casse:
SELECT balance FROM people WHERE email = 'billg@microsoft.com'
COLLATE SQL_Latin1_General_CP1_CI_AS
J'ai trouvé une autre solution ailleurs; c'est-à-dire utiliser
upper(@yourString)
mais tout le monde ici dit que, dans SQL Server, cela n'a pas d'importance car il ignore de toute façon la casse? Je suis presque sûr que notre base de données est sensible à la casse.
Les 2 premières réponses (d' Adam Robinson et Andrejs Cainikovs ) sont un peu, plutôt correctes, en ce sens qu'elles fonctionnent techniquement, mais leurs explications sont erronées et pourraient donc être trompeuses dans de nombreux cas. Par exemple, bien que le SQL_Latin1_General_CP1_CI_AS
classement fonctionne dans de nombreux cas, il ne doit pas être supposé être le classement insensible à la casse approprié. En fait, étant donné que l'OP fonctionne dans une base de données avec un classement sensible à la casse (ou éventuellement binaire), nous savons que l'OP n'utilise pas le classement par défaut pour tant d'installations (en particulier celles installées sur un OS en utilisant l' anglais américain comme langue): SQL_Latin1_General_CP1_CI_AS
. Bien sûr, l'OP pourrait utiliser SQL_Latin1_General_CP1_CS_AS
, mais lorsque vous travaillez avecVARCHAR
données, il est important de ne pas changer la page de codes car cela pourrait entraîner une perte de données, et cela est contrôlé par la langue / la culture du classement (c'est-à-dire Latin1_General vs French vs Hebrew, etc.). Veuillez consulter le point 9 ci-dessous.
Les quatre autres réponses sont fausses à des degrés divers.
Je vais clarifier tous les malentendus ici afin que les lecteurs puissent, espérons-le, faire les choix les plus appropriés / efficaces.
Ne l'utilisez pas UPPER()
. C'est un travail supplémentaire complètement inutile. Utilisez une COLLATE
clause. Une comparaison de chaînes doit être effectuée dans les deux cas, mais l'utilisation UPPER()
doit également vérifier, caractère par caractère, s'il existe un mappage en majuscules, puis le modifier. Et vous devez le faire des deux côtés. L'ajout demande COLLATE
simplement au traitement de générer les clés de tri en utilisant un ensemble de règles différent de celui auquel il était destiné par défaut. L'utilisation COLLATE
est nettement plus efficace (ou "performante", si vous aimez ce mot :) que l'utilisation UPPER()
, comme le prouve ce script de test (sur PasteBin) .
Il y a aussi le problème noté par @Ceisc sur la réponse de @ Danny:
Dans certaines langues, les conversions de cas ne sont pas aller-retour. c'est-à-dire INFÉRIEUR (x)! = INFÉRIEUR (SUPÉRIEUR (x)).
La majuscule turque "İ" est l'exemple courant.
Non, le classement n'est pas un paramètre à l'échelle de la base de données, du moins pas dans ce contexte. Il existe un classement par défaut au niveau de la base de données, et il est utilisé par défaut pour les colonnes modifiées et nouvellement créées qui ne spécifient pas la COLLATE
clause (ce qui est probablement la source de cette idée fausse commune), mais elle n'a pas d'incidence directe sur les requêtes, sauf si vous êtes comparer des littéraux de chaîne et des variables à d'autres littéraux de chaîne et variables, ou vous faites référence à des métadonnées au niveau de la base de données.
Non, le classement n'est pas par requête.
Les classements sont par prédicat (c'est-à-dire quelque chose d'opérande) ou expression, pas par requête. Et cela est vrai pour l'ensemble de la requête, pas seulement pour la WHERE
clause. Cela couvre les JOINs, GROUP BY, ORDER BY, PARTITION BY, etc.
Non, ne pas convertir en VARBINARY
(par exemple convert(varbinary, myField) = convert(varbinary, 'sOmeVal')
) pour les raisons suivantes:
_BIN2
si vous utilisez SQL Server 2008 ou plus récent, sinon vous n'avez pas d'autre choix que d'en utiliser un qui se termine par _BIN
. Si les données le sont, NVARCHAR
peu importe la langue que vous utilisez, car elles sont toutes identiques dans ce cas, elles fonctionnent donc Latin1_General_100_BIN2
toujours. Si les données VARCHAR
, vous devez utiliser les mêmes paramètres régionaux que les données sont actuellement (par exemple Latin1_General
, French
, Japanese_XJIS
, etc.) parce que les paramètres régionaux détermine la page de code qui est utilisé, et la modification des pages de code peut modifier les données (perte de données).CONVERT()
il utilisera la valeur par défaut 30. Le danger est que si la chaîne peut dépasser 30 octets, elle sera silencieusement tronquée et vous obtiendrez probablement des résultats incorrects de ce prédicat.Non, LIKE
n'est pas toujours sensible à la casse. Il utilise le classement de la colonne référencée, ou le classement de la base de données si une variable est comparée à un littéral de chaîne, ou le classement spécifié via la COLLATE
clause facultative .
LCASE
n'est pas une fonction SQL Server. Il semble que ce soit Oracle ou MySQL. Ou peut-être Visual Basic?
Étant donné que le contexte de la question compare une colonne à un littéral de chaîne, ni le classement de l'instance (souvent appelé «serveur») ni le classement de la base de données n'ont ici d'impact direct . Les classements sont stockés pour chaque colonne et chaque colonne peut avoir un classement différent, et ces classements n'ont pas besoin d'être les mêmes que le classement par défaut de la base de données ou le classement de l'instance. Bien sûr, le classement des instances est le classement par défaut de ce qu'une base de données nouvellement créée utilisera comme classement par défaut si la COLLATE
clause n'a pas été spécifiée lors de la création de la base de données. Et de même, le classement par défaut de la base de données est ce qu'une colonne modifiée ou nouvellement créée utilisera si la COLLATE
clause n'a pas été spécifiée.
Vous devez utiliser le classement insensible à la casse qui est sinon le même que le classement de la colonne. Utilisez la requête suivante pour trouver le classement de la colonne (modifiez le nom de la table et le nom du schéma):
SELECT col.*
FROM sys.columns col
WHERE col.[object_id] = OBJECT_ID(N'dbo.TableName')
AND col.[collation_name] IS NOT NULL;
Ensuite, changez simplement le _CS
pour être _CI
. Alors, Latin1_General_100_CS_AS
deviendrait Latin1_General_100_CI_AS
.
Si la colonne utilise un classement binaire (se terminant par _BIN
ou _BIN2
), recherchez un classement similaire à l'aide de la requête suivante:
SELECT *
FROM sys.fn_helpcollations() col
WHERE col.[name] LIKE N'{CurrentCollationMinus"_BIN"}[_]CI[_]%';
Par exemple, en supposant que la colonne utilise Japanese_XJIS_100_BIN2
, procédez comme suit:
SELECT *
FROM sys.fn_helpcollations() col
WHERE col.[name] LIKE N'Japanese_XJIS_100[_]CI[_]%';
Pour plus d' informations sur les classements, codages, etc., visitez s'il vous plaît: collation Infos
Non, seule l'utilisation LIKE
ne fonctionnera pas. LIKE
recherche des valeurs correspondant exactement à votre modèle donné. Dans ce cas LIKE
, trouverait uniquement le texte «sOmeVal» et non «someval».
Une solution pratique consiste à utiliser la LCASE()
fonction. LCASE('sOmeVal')
obtient la chaîne minuscule de votre texte: 'someval'. Si vous utilisez cette fonction pour les deux côtés de votre comparaison, cela fonctionne:
SELECT * FROM myTable WHERE LCASE(myField) LIKE LCASE('sOmeVal')
L'instruction compare deux chaînes minuscules, de sorte que votre 'sOmeVal' correspondra à toutes les autres notations de 'someval' (par exemple 'Someval', 'sOMEVAl' etc.).
LCASE()
dans SQL Server (du moins pas que je puisse voir). Je pense que cette réponse est pour un SGBDR entièrement différent. Veuillez consulter ma réponse pour obtenir des précisions sur les comparaisons de chaînes.
Vous pouvez forcer la sensibilité à la casse, en effectuant un cast en varbinary comme ça:
SELECT * FROM myTable
WHERE convert(varbinary, myField) = convert(varbinary, 'sOmeVal')
Sur quelle base de données êtes-vous? Avec MS SQL Server, il s'agit d'un paramètre à l'échelle de la base de données, ou vous pouvez le remplacer par requête avec le mot clé COLLATE.
WHERE
déclaration, et affectera toutes lesWHERE
clauses, n'est-ce pas?