Как выполнить поиск с учетом регистра в предложении WHERE (я использую SQL Server)?

150

Я хочу сделать поиск с учетом регистра в моем запросе SQL. Но по умолчанию SQL Server не учитывает регистр строк.

Любая идея о том, как сделать регистрозависимый поиск в запросе SQL?

Веера
источник

Ответы:

174

Это можно сделать, изменив параметры сортировки . По умолчанию регистр не учитывается.

Выдержка из ссылки:

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

Или измените столбцы с учетом регистра .

Ашиш Джайн
источник
2
Как использовать, когда у нас есть вместо =. как ГДЕ CustID в (@CustID)
rinuthomaz
Сличение работает в большинстве случаев, но если в ваших данных есть другие языковые символы, оно будет возвращать ложные срабатывания: /schwarz-weißпротив:/schwarz-weiss
Lazlow
162

Используя сопоставление или приведение к двоичному виду, вот так:

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 

Дублирование имени пользователя / пароля существует, чтобы дать движку возможность использовать индексы. Приведенное выше сопоставление является сопоставлением с учетом регистра, при необходимости измените его на нужное.

Второй, приведение к двоичному, можно сделать так:

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 
Джонас Линкольн
источник
13
Люди, читающие этот вопрос, могут также найти полезным прочитать, как изменить сам столбец, чтобы он учитывал регистр, что устраняет необходимость использования параметров сортировки в предложении WHERE. См .: stackoverflow.com/a/485394/908677
Элайджа Лофгрен
2
Метод приведения как varbinary работал для меня, когда он использовался непосредственно в базе данных, но не работал при отправке того же оператора из приложения .NET - понятия не имею, почему. Но метод сопоставления работал хорошо.
Дуг
1
Этот ответ был бы идеальным, если бы он включал в себя объяснение того, куда помещать искомый термин, т. Е. Где like "*word or phrase*"будет вставлена фраза, похожая на обычный поиск SQL.
Консервированный человек
@CannedMan - Вы можете использовать вышеупомянутое сопоставление таким же образом с оператором LIKE. Просто сделайте следующее, чтобы вернуть все буквы D в верхнем регистре. «SELECT * FROM SomeTable WHERE ColumnName наподобие«% D% »COLLATE SQL_Latin1_General_CP1_CS_AS»
Radderz
Это не работает с чешским алфавитом. Проверенное слово: «ukázka». Оно находится в таблице как отдельное слово в столбце, но ваш поиск не нашел его.
Ян Мачачек
14

Вы можете сделать запрос с помощью конвертации в varbinary - это очень просто. Пример:

Select * from your_table where convert(varbinary, your_column) = convert(varbinary, 'aBcD') 
Хуан Карлос Велес
источник
2
Это не работает с чешским алфавитом. Проверенное слово: «ukázka». Оно находится в таблице как отдельное слово в столбце, но ваш поиск не нашел его.
Ян Мачачек
7

USE BINARY_CHECKSUM

SELECT 
FROM Users
WHERE   
    BINARY_CHECKSUM(Username) = BINARY_CHECKSUM(@Username)
    AND BINARY_CHECKSUM(Password) = BINARY_CHECKSUM(@Password)
Sandeep
источник
3
Разве это не значит, что это уже не точное сравнение? Может быть, иногда это возвращает истину, что они на самом деле не одинаковы?
О'Руни
3
Я согласен, @ O'Rooney, это иногда возвращает ложные срабатывания.
Des Horsley
5

использовать хэшбайты

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

... в пункте, где

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

или найти значение

declare @value_b nvarchar(1) = 'A'

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

-- output:
-- A = A
ровнять
источник
5

используйте Latin1_General_CS в качестве сопоставления в вашей базе данных sql

Blake
источник
2

В MySQL, если вы не хотите изменять параметры сортировки и хотите выполнять поиск с учетом регистра, просто используйте двоичное ключевое слово, например:

SELECT * FROM table_name WHERE binary username=@search_parameter and binary password=@search_parameter
Сумит Джоши
источник
2
Это неверный запрос SQL Server. Я думаю, что это MySQL
Джон
2
Отлично работает на MySQL
WM
1
select * from incidentsnew1 
where BINARY_CHECKSUM(CloseBy) = BINARY_CHECKSUM(Upper(CloseBy))
Хемант Ядав
источник
-4

Как и другие говорили, вы можете выполнять поиск с учетом регистра. Или просто измените формат сопоставления указанного столбца как я. Для столбцов User / Password в моей базе данных я изменяю их на параметры сортировки с помощью следующей команды:

ALTER TABLE `UserAuthentication` CHANGE `Password` `Password` VARCHAR(255) CHARACTER SET latin1 COLLATE latin1_general_cs NOT NULL;
Gfast2
источник
НЕ храните пароли в виде открытого текста! Они должны были быть перемешаны и посолены, а затем сравнение по хешу и соли! Это просто ужасный ответ!
Нельсон