Подтвердить что ты не робот

SQL Server игнорирует регистр в выражении where

Как я могу построить SQL-запрос (MS SQL Server), где предложение "where" нечувствительно к регистру?

SELECT * FROM myTable WHERE myField = 'sOmeVal'

Я хочу, чтобы результаты вернулись, игнорируя случай

4b9b3361

Ответ 1

В стандартной конфигурации базы данных SQL Server сравнение строк нечувствительно к регистру. Если ваша база данных отменяет этот параметр (с помощью альтернативной сортировки), вам нужно указать, какой тип сортировки использовать в вашем запросе.

SELECT * FROM myTable WHERE myField = 'sOmeVal' COLLATE SQL_Latin1_General_CP1_CI_AS

Обратите внимание, что предоставленное мной сопоставление - это просто пример (хотя это будет более чем вероятно, просто отлично подходит для вас). Более подробное описание коллизий SQL Server можно найти здесь.

Ответ 2

Обычно сравнения строк нечувствительны к регистру. Если ваша база данных настроена на сортировку с учетом регистра, вам необходимо принудительно использовать регистр, нечувствительный к регистру:

SELECT balance FROM people WHERE email = '[email protected]'
  COLLATE SQL_Latin1_General_CP1_CI_AS 

Ответ 3

Я нашел другое решение в другом месте; то есть использовать

upper(@yourString)

но все здесь говорят, что в SQL Server это не имеет значения, потому что это игнорирует случай? Я уверен, что наша база данных чувствительна к регистру.

Ответ 4

Нет, только использование LIKE не будет работать. LIKE выполняет поиск значений, соответствующих точно данному шаблону. В этом случае LIKE найдет только текст 'sOmeVal', а не 'someval'.

Решающее решение использует функцию LCASE(). LCASE('sOmeVal') получает строчную строку вашего текста: "someval". Если вы используете эту функцию для обеих сторон вашего сравнения, она работает:

SELECT * FROM myTable WHERE LCASE(myField) LIKE LCASE('sOmeVal')

Оператор сравнивает две строчные строки, так что ваш 'sOmeVal' будет соответствовать любой другой нотации 'someval' (например, "Someval", "sOMEVAl" и т.д.).

Ответ 5

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

SELECT * FROM myTable 
WHERE convert(varbinary, myField) = convert(varbinary, 'sOmeVal')

Ответ 6

Лучшие 2 ответа (от Адама Робинсона и Андрея Каиниковых) довольно правильные, поскольку они технически работают, но их объяснения неверны и во многих случаях могут вводить в заблуждение. Например, хотя сортировка SQL_Latin1_General_CP1_CI_AS будет работать во многих случаях, ее не следует рассматривать как подходящую сортировку без SQL_Latin1_General_CP1_CI_AS регистра. Фактически, учитывая, что OP работает в базе данных с сортировкой с учетом регистра (или, возможно, двоичным кодом), мы знаем, что OP не использует сортировку, которая используется по умолчанию для столь многих установок (особенно любой, установленной в ОС). используя американский английский в качестве языка): SQL_Latin1_General_CP1_CI_AS. Конечно, OP может использовать SQL_Latin1_General_CP1_CS_AS, но при работе с данными VARCHAR важно не изменять кодовую страницу, так как это может привести к потере данных, и это контролируется языком/культурой сопоставления (т.е. Latin1_General vs French против иврита и т.д.). Пожалуйста, смотрите пункт № 9 ниже.

Остальные четыре ответа неверны в разной степени.

Я проясню все недоразумения, чтобы читатели могли сделать наиболее подходящий/эффективный выбор.

  1. Не используйте UPPER(). Это совершенно ненужная дополнительная работа. Используйте предложение COLLATE. Сравнение строк необходимо выполнить в любом случае, но использование UPPER() также должно проверять, символ за символом, чтобы увидеть, есть ли отображение в верхнем регистре, а затем изменить его. И вам нужно сделать это с обеих сторон. Добавление COLLATE просто направляет обработку для генерации ключей сортировки с использованием набора правил, отличного от того, который использовался по умолчанию. Использование COLLATE определенно более эффективно (или "производительно", если вам нравится это слово :), чем использование UPPER(), как доказано в этом тестовом скрипте (в PasteBin).

    Существует также проблема, отмеченная @Ceisc в ответе @Danny:

    В некоторых языках конверсии делаются не туда и обратно. то есть НИЖНЯЯ (х)! = НИЖНЯЯ (ВЕРХНЯЯ (х)).

    Турецкий верхний регистр "İ" является распространенным примером.

  2. Нет, сортировка не является настройкой всей базы данных, по крайней мере, не в этом контексте. Существует сопоставление по умолчанию на уровне базы данных, и оно используется в качестве значения по умолчанию для измененных и вновь создаваемых столбцов, в которых не указано предложение COLLATE (что, вероятно, связано с этим распространенным заблуждением), но оно не влияет на запросы напрямую, если только вы сравниваете строковые литералы и переменные с другими строковыми литералами и переменными или ссылаетесь на метаданные уровня базы данных.

  3. Нет, сопоставление не по запросу.

  4. Сопоставления производятся по предикату (то есть что-то операнду) или выражению, а не по запросу. И это верно для всего запроса, а не только для WHERE. Это включает в себя СОЕДИНЕНИЯ, ГРУППЫ BY, ORDER BY, PARTITION BY и т.д.

  5. Нет, не конвертировать в VARBINARY (например, convert(varbinary, myField) = convert(varbinary, 'sOmeVal')) по следующим причинам:

    1. это бинарное сравнение, которое не учитывает регистр (вот что задает этот вопрос)
    2. если вы хотите двоичное сравнение, используйте двоичное сопоставление. Используйте тот, который заканчивается на _BIN2 если вы используете SQL Server 2008 или новее, иначе у вас нет другого выбора, кроме как использовать тот, который заканчивается на _BIN. Если данные NVARCHAR то не имеет значения, какую локаль вы используете, так как они все одинаковые в этом случае, поэтому Latin1_General_100_BIN2 всегда работает. Если данные VARCHAR, вы должны использовать ту же локаль, в которой находятся данные (например, Latin1_General, French, Japanese_XJIS и т.д.), Потому что локаль определяет используемую кодовую страницу, и изменение кодовых страниц может изменить данные (т.е. данные потеря).
    3. использование типа данных переменной длины без указания размера будет зависеть от размера по умолчанию, и существуют два различных значения по умолчанию в зависимости от контекста, в котором используется тип данных. Это либо 1, либо 30 для строковых типов. При использовании с CONVERT() он будет использовать значение по умолчанию 30. Опасность заключается в том, что если длина строки может превышать 30 байт, она будет молча усечена, и вы, вероятно, получите неверные результаты из этого предиката.
    4. Даже если вы хотите сравнение с учетом регистра, двоичные сопоставления не учитывают регистр (еще одно очень распространенное заблуждение).
  6. Нет, LIKE не всегда чувствителен к регистру. Он использует сопоставление столбца, на который ссылаются, или сопоставление базы данных, если переменная сравнивается со строковым литералом, или сопоставление, указанное в необязательном предложении COLLATE.

  7. LCASE не является функцией SQL Server. Похоже, это либо Oracle, либо MySQL. Или, возможно, Visual Basic?

  8. Поскольку контекст вопроса сравнивает столбец со строковым литералом, то ни сопоставление экземпляра (часто называемое "сервером"), ни сопоставление базы данных не имеют здесь никакого прямого влияния. Параметры сортировки хранятся для каждого столбца, и каждый столбец может иметь разные параметры сортировки, и эти параметры сортировки не обязательно должны совпадать с параметрами сортировки базы данных по умолчанию или параметров сортировки экземпляра. Конечно, сопоставление экземпляра является значением по умолчанию для того, что вновь созданная база данных будет использовать в качестве сопоставления по умолчанию, если при создании базы данных не было указано условие COLLATE. Аналогично, сортировка по умолчанию для базы данных - это то, что будет использовать измененный или только что созданный столбец, если не было указано предложение COLLATE.

  9. Следует использовать сопоставление без учета регистра, которое в остальном совпадает с сопоставлением столбца. Используйте следующий запрос, чтобы найти параметры сортировки столбцов (измените имя таблицы и имя схемы):

    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 информацию

Ответ 7

В какой базе данных вы работаете? С MS SQL Server это параметр базы данных, или вы можете перегрузить его для каждого запроса с помощью ключевого слова COLLATE.