Как создать SQL-запрос (MS SQL Server), в котором в предложении «where» регистр не учитывается?
SELECT * FROM myTable WHERE myField = 'sOmeVal'
Я хочу, чтобы результаты вернулись, не обращая внимания на дело
sql
sql-server
where-clause
case-insensitive
Рауль Аграйт
источник
источник
WHERE
оператора, и это повлияет на всеWHERE
предложения, верно?UPPER
илиLOWER
регистр, а затем использоватьLIKE
для поиска?Обычно при сравнении строк регистр не учитывается. Если ваша база данных настроена на сортировку с учетом регистра, вам необходимо принудительно использовать регистронезависимую:
SELECT balance FROM people WHERE email = 'billg@microsoft.com' COLLATE SQL_Latin1_General_CP1_CI_AS
источник
Я нашел другое решение в другом месте; то есть использовать
но все здесь говорят, что в SQL Server это не имеет значения, потому что он все равно игнорирует регистр? Я почти уверен, что наша база данных чувствительна к регистру.
источник
Два основных ответа (от Адама Робинсона и Андрея Кайникова ) в некотором роде верны в том смысле, что они технически работают, но их объяснения неверны и поэтому во многих случаях могут вводить в заблуждение. Например, хотя
SQL_Latin1_General_CP1_CI_AS
сопоставление будет работать во многих случаях, не следует предполагать, что оно является подходящим сопоставлением без учета регистра. Фактически, учитывая, что OP работает в базе данных с чувствительным к регистру (или, возможно, двоичным) сопоставлением, мы знаем, что OP не использует сопоставление, которое является значением по умолчанию для многих установок (особенно тех, которые установлены в ОС. используя американский английский как язык):SQL_Latin1_General_CP1_CI_AS
. Конечно, OP можно использоватьSQL_Latin1_General_CP1_CS_AS
, но при работе сVARCHAR
data, важно не изменять кодовую страницу, так как это может привести к потере данных, и это контролируется локалью / культурой сопоставления (например, Latin1_General vs French vs Hebrew и т. д.). См. Пункт 9 ниже.Остальные четыре ответа в той или иной степени неверны.
Я проясню здесь все недоразумения, чтобы читатели могли, надеюсь, сделать наиболее подходящий / эффективный выбор.
Не использовать
UPPER()
. Это совершенно ненужная дополнительная работа. ИспользуйтеCOLLATE
предложение. В любом случае необходимо выполнить сравнение строк, но при использованииUPPER()
также необходимо проверять символ за символом, чтобы увидеть, есть ли отображение в верхнем регистре, а затем изменить его. Причем делать это нужно с обеих сторон. ДобавлениеCOLLATE
просто направляет обработку для создания ключей сортировки с использованием набора правил, отличного от того, который использовался по умолчанию. ИспользованиеCOLLATE
определенно более эффективно (или «производительно», если вам нравится это слово :), чем использованиеUPPER()
, как показано в этом тестовом сценарии (на PasteBin) .Существует также проблема, отмеченная @Ceisc в ответе @Danny:
Турецкая заглавная буква «İ» является типичным примером.
Нет, сортировка не является параметром всей базы данных, по крайней мере, в этом контексте. Существует сопоставление по умолчанию на уровне базы данных, и оно используется по умолчанию для измененных и вновь созданных столбцов, в которых не указано
COLLATE
условие (что, вероятно, является источником этого распространенного заблуждения), но оно не влияет на запросы напрямую, если вы не сравнение строковых литералов и переменных с другими строковыми литералами и переменными, или вы ссылаетесь на метаданные уровня базы данных.Нет, сортировка выполняется не по запросу.
Сопоставления выполняются для каждого предиката (т.е. чего-то операнда чего-то) или выражения, а не запроса. И это верно для всего запроса, а не только для
WHERE
предложения. Это касается JOINs, GROUP BY, ORDER BY, PARTITION BY и т. Д.Нет, не конвертируйте в
VARBINARY
(напримерconvert(varbinary, myField) = convert(varbinary, 'sOmeVal')
) по следующим причинам:_BIN2
если вы используете SQL Server 2008 или новее, иначе у вас нет выбора, кроме как использовать тот, который заканчивается на_BIN
. Если данные есть,NVARCHAR
то не имеет значения, какой язык вы используете, поскольку в этом случае они все одинаковы, следовательно,Latin1_General_100_BIN2
всегда работает. Если данныеVARCHAR
, вы должны использовать один и тот же локаль , что данные в настоящее время (напримерLatin1_General
,French
,Japanese_XJIS
и т.д.) , так как локаль определяет кодовую страницу, которая используется, и изменения кода страницы могут изменять данные (т.е. потери данных).CONVERT()
ним будет использоваться значение по умолчанию 30. Опасность заключается в том, что если длина строки может превышать 30 байт, она будет автоматически усечена, и вы, вероятно, получите неверные результаты из этого предиката.Нет,
LIKE
не всегда с учетом регистра. Он использует сопоставление столбца, на который указывает ссылка, или сопоставление базы данных, если переменная сравнивается со строковым литералом, или сопоставление, указанное с помощью необязательногоCOLLATE
предложения.LCASE
не является функцией SQL Server. Похоже, это либо Oracle, либо MySQL. Или, возможно, Visual Basic?Поскольку контекст вопроса - сравнение столбца со строковым литералом, ни сортировка экземпляра (часто называемая «сервером»), ни сортировка базы данных не имеют здесь прямого влияния. Параметры сортировки хранятся для каждого столбца, и каждый столбец может иметь разные параметры сортировки, и эти параметры сортировки не обязательно должны совпадать с параметрами сортировки по умолчанию в базе данных или параметрами сортировки экземпляра. Конечно, сортировка экземпляра - это значение по умолчанию для того, что вновь созданная база данных будет использовать в качестве сопоставления по умолчанию, если
COLLATE
предложение не было указано при создании базы данных. Точно так же параметры сортировки по умолчанию для базы данных - это то, что будет использовать измененный или вновь созданный столбец, еслиCOLLATE
предложение не было указано.Следует использовать параметры сортировки без учета регистра, которые в остальном аналогичны параметрам сортировки столбца. Используйте следующий запрос, чтобы найти параметры сортировки столбца (измените имя таблицы и имя схемы):
SELECT col.* FROM sys.columns col WHERE col.[object_id] = OBJECT_ID(N'dbo.TableName') AND col.[collation_name] IS NOT NULL;
Тогда просто измените значение
_CS
на быть_CI
. Итак,Latin1_General_100_CS_AS
стал быLatin1_General_100_CI_AS
.Если в столбце используется двоичная сортировка (оканчивающаяся на
_BIN
или_BIN2
), найдите аналогичную сортировку, используя следующий запрос:SELECT * FROM sys.fn_helpcollations() col WHERE col.[name] LIKE N'{CurrentCollationMinus"_BIN"}[_]CI[_]%';
Например, предполагая, что столбец используется
Japanese_XJIS_100_BIN2
, сделайте следующее:SELECT * FROM sys.fn_helpcollations() col WHERE col.[name] LIKE N'Japanese_XJIS_100[_]CI[_]%';
Для получения дополнительной информации о параметрах сортировки, кодировки, и т.д., пожалуйста , посетите: Collations информацию
источник
Нет, только с помощью
LIKE
не получится.LIKE
ищет значения, точно соответствующие вашему заданному шаблону. В этом случаеLIKE
будет найден только текст «sOmeVal», а не «someval».Практическое решение - использовать
LCASE()
функцию.LCASE('sOmeVal')
получает строчную строку вашего текста: 'someval'. Если вы используете эту функцию для обеих сторон своего сравнения, она работает:SELECT * FROM myTable WHERE LCASE(myField) LIKE LCASE('sOmeVal')
Этот оператор сравнивает две строчные строки, так что ваш 'sOmeVal' будет соответствовать всем другим обозначениям 'someval' (например, 'Someval', 'sOMEVAl' и т. Д.).
источник
LCASE()
в SQL Server (по крайней мере, я не вижу). Я думаю, что это ответ для совершенно другой СУБД. Пожалуйста, посмотрите мой ответ, чтобы прояснить сравнение строк.Вы можете принудительно использовать регистр, приведя к такому типу varbinary:
SELECT * FROM myTable WHERE convert(varbinary, myField) = convert(varbinary, 'sOmeVal')
источник
В какой базе данных вы находитесь? В MS SQL Server это параметр для всей базы данных, или вы можете переопределить его для каждого запроса с помощью ключевого слова COLLATE.
источник