Comment faire une recherche sensible à la casse dans la clause WHERE (j'utilise SQL Server)?

150

Je souhaite effectuer une recherche sensible à la casse dans ma requête SQL. Mais par défaut, SQL Server ne considère pas la casse des chaînes.

Une idée sur la façon de faire une recherche sensible à la casse dans une requête SQL?

Veera
la source

Réponses:

174

Peut être fait en changeant le classement . Par défaut, il est insensible à la casse.

Extrait du lien:

SELECT 1
FROM dbo.Customers
WHERE   CustID = @CustID COLLATE SQL_Latin1_General_CP1_CS_AS
    AND CustPassword = @CustPassword COLLATE SQL_Latin1_General_CP1_CS_AS

Ou modifiez les colonnes pour qu'elles respectent la casse .

Ashish Jain
la source
2
Comment utiliser quand nous avons à la place =. comme WHERE CustID dans (@CustID)
rinuthomaz
Le classement fonctionne dans la plupart des cas, mais si vous avez d'autres caractères de langue dans vos données, il renverra des faux positifs: /schwarz-weißcontre:/schwarz-weiss
Lazlow
162

En utilisant le classement ou la conversion en binaire, comme ceci:

SELECT *
FROM Users
WHERE   
    Username = @Username COLLATE SQL_Latin1_General_CP1_CS_AS
    AND Password = @Password COLLATE SQL_Latin1_General_CP1_CS_AS
    AND Username = @Username 
    AND Password = @Password 

La duplication du nom d'utilisateur / mot de passe existe pour donner au moteur la possibilité d'utiliser des index. Le classement ci-dessus est un classement sensible à la casse, remplacez-le par celui dont vous avez besoin si nécessaire.

Le second, la conversion en binaire, pourrait être fait comme ceci:

SELECT *
FROM Users
WHERE   
    CAST(Username as varbinary(100)) = CAST(@Username as varbinary))
    AND CAST(Password as varbinary(100)) = CAST(@Password as varbinary(100))
    AND Username = @Username 
    AND Password = @Password 
Jonas Lincoln
la source
13
Les personnes lisant cette question peuvent également trouver utile de lire comment modifier la colonne elle-même pour qu'elle respecte la casse, ce qui élimine le besoin d'utiliser le classement dans la clause WHERE. Voir: stackoverflow.com/a/485394/908677
Elijah Lofgren
2
La méthode cast as varbinary fonctionnait pour moi lorsqu'elle était utilisée directement sur la base de données, mais ne fonctionnait pas lors de l'envoi de la même instruction à partir d'une application .NET - aucune idée de pourquoi. Mais la méthode d'assemblage a bien fonctionné.
Doug le
1
Cette réponse serait parfaite si elle incluait une explication de l'endroit où placer le terme recherché, c'est-à-dire où la phrase similaire à une like "*word or phrase*"recherche SQL régulière serait insérée.
Canned Man
@CannedMan - Vous pouvez utiliser la solution d'assemblage ci-dessus de la même manière avec l'instruction LIKE. Procédez simplement comme suit pour renvoyer tous les D majuscules. "SELECT * FROM SomeTable WHERE ColumnName comme '% D%' COLLATE SQL_Latin1_General_CP1_CS_AS"
Radderz
Cela ne fonctionne pas avec l'alphabet tchèque. Mot testé: «ukázka». Il figure dans le tableau sous la forme d'un seul mot dans une colonne, mais votre recherche ne l'a pas trouvé.
Jan Macháček
14

Vous pouvez effectuer la requête en utilisant convert to varbinary - c'est très simple. Exemple:

Select * from your_table where convert(varbinary, your_column) = convert(varbinary, 'aBcD') 
Juan Carlos Velez
la source
2
Cela ne fonctionne pas avec l'alphabet tchèque. Mot testé: «ukázka». Il figure dans le tableau sous la forme d'un seul mot dans une colonne, mais votre recherche ne l'a pas trouvé.
Jan Macháček
7

UTILISER BINARY_CHECKSUM

SELECT 
FROM Users
WHERE   
    BINARY_CHECKSUM(Username) = BINARY_CHECKSUM(@Username)
    AND BINARY_CHECKSUM(Password) = BINARY_CHECKSUM(@Password)
Sandeep
la source
3
Cela ne voudrait-il pas dire que ce n'est plus une comparaison exacte? Il peut y avoir parfois que cela renvoie vrai qu'ils ne sont pas réellement les mêmes?
O'Rooney
3
Je suis d'accord @ O'Rooney que cela renverra parfois de faux positifs.
Des Horsley
5

utiliser HASHBYTES

declare @first_value nvarchar(1) = 'a'
declare @second_value navarchar(1) = 'A'

if HASHBYTES('SHA1',@first_value) = HASHBYTES('SHA1',@second_value) begin
    print 'equal'
end else begin
    print 'not equal'
end

-- output:
-- not equal

... dans la clause where

declare @example table (ValueA nvarchar(1), ValueB nvarchar(1))

insert into @example (ValueA, ValueB)
values  ('a', 'A'),
        ('a', 'a'),
        ('a', 'b')

select  ValueA + ' = ' + ValueB
from    @example
where   hashbytes('SHA1', ValueA) = hashbytes('SHA1', ValueB)

-- output:
-- a = a

select  ValueA + ' <> ' + ValueB
from    @example
where   hashbytes('SHA1', ValueA) <> hashbytes('SHA1', ValueB)

-- output:
-- a <> A
-- a <> b

ou pour trouver une valeur

declare @value_b nvarchar(1) = 'A'

select  ValueB + ' = ' + @value_b
from    @example
where   hashbytes('SHA1', ValueB) = hasbytes('SHA1', @value_b)

-- output:
-- A = A
Dub
la source
5

utilisez Latin1_General_CS comme classement dans votre base de données SQL

blake
la source
2

Dans MySQL, si vous ne souhaitez pas modifier le classement et que vous souhaitez effectuer une recherche sensible à la casse, utilisez simplement un mot-clé binaire comme celui-ci:

SELECT * FROM table_name WHERE binary username=@search_parameter and binary password=@search_parameter
Sumit Joshi
la source
2
Ce n'est pas une requête SQL Server valide. Je pense que c'est MySQL
Jon Tirjan
2
Fonctionne parfaitement sur MySQL
WM
1
select * from incidentsnew1 
where BINARY_CHECKSUM(CloseBy) = BINARY_CHECKSUM(Upper(CloseBy))
Hemant yadav
la source
-4

Comme d'autres l'ont dit, vous pouvez effectuer une recherche sensible à la casse. Ou changez simplement le format de classement d'une colonne spécifiée comme moi. Pour les colonnes Utilisateur / Mot de passe de ma base de données, je les change en classement via la commande suivante:

ALTER TABLE `UserAuthentication` CHANGE `Password` `Password` VARCHAR(255) CHARACTER SET latin1 COLLATE latin1_general_cs NOT NULL;
Gfast2
la source
Ne stockez PAS les mots de passe sous forme de texte brut! Ils auraient dû être hachés et salés, puis la comparaison porte sur le hasch et le sel! C'est simplement une réponse terrible!
Nelson le