SQL-сервер игнорирует регистр в выражении where - PullRequest
77 голосов
/ 04 августа 2009

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

SELECT * FROM myTable WHERE myField = 'sOmeVal'

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

Ответы [ 7 ]

119 голосов
/ 04 августа 2009

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

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

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

28 голосов
/ 04 августа 2009

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

SELECT balance FROM people WHERE email = 'billg@microsoft.com'
  COLLATE SQL_Latin1_General_CP1_CI_AS 
20 голосов
/ 16 июля 2010

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

upper(@yourString)

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

7 голосов
/ 02 октября 2012

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

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

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

Оператор сравнивает две строчные строчные буквы, так что ваш sOmeVal будет соответствовать всем другим обозначениям someval (например, Someval, sOMEVAl и т. Д.).

6 голосов
/ 30 января 2019

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

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

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

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

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

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

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

  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. Поскольку контекст вопроса сравнивает столбец со строковым литералом, ни параметры сортировки экземпляра (часто называемого «сервером»), ни параметры сопоставления базы данных не имеют direct влияние здесь. Параметры сортировки хранятся для каждого столбца, и каждый столбец может иметь разные параметры сортировки, и эти параметры сортировки не обязательно должны быть такими же, как параметры сортировки базы данных по умолчанию или параметры сортировки экземпляра. Конечно, сопоставление экземпляра является значением по умолчанию для того, что вновь созданная база данных будет использовать в качестве сопоставления по умолчанию, если при создании базы данных не было указано условие 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[_]%';
    

Для получения дополнительной информации о сопоставлениях, кодировках и т. Д. Посетите: Сведения о сопоставлениях

3 голосов
/ 04 августа 2009

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

SELECT * FROM myTable 
WHERE convert(varbinary, myField) = convert(varbinary, 'sOmeVal')
2 голосов
/ 04 августа 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...