Учитывает ли регистр оператора LIKE в MSSQL Server?


99

В документации к оператору LIKE ничего не сказано о его чувствительности к регистру. Это? Как включить / выключить?

Я запрашиваю varchar(n)столбцы при установке Microsoft SQL Server 2005, если это важно.


14
Это зависит от параметров сортировки вашего столбца (или базы данных). Если он чувствителен к регистру, то LIKEон чувствителен к регистру, если нет, то LIKEнет
Ламак

Ознакомьтесь с документацией о сопоставлениях SQL-Server msdn.microsoft.com/en-us/library/ms144250%28v=sql.105%29.aspx
GarethD

Какова ваша цель? Вы хотите, чтобы регистр учитывался или не учитывал регистр?
Аарон Бертран,

1
По умолчанию чувствительность к регистру соответствует параметрам сортировки в столбце, который по умолчанию равен столбцу в базе данных. В основном это можно округлить, какой путь вы хотите пойти?
Тони Хопкинсон

Ответы:


101

Регистр учитывается не в операторе, а в самом столбце.

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

Подобное сопоставление sql_latin1_general_cp1_ci_asопределяет, как следует обрабатывать содержимое столбца. CI означает нечувствительность к регистру, а AS - чувствительность к акцентам.

Полный список сопоставлений доступен по адресу https://msdn.microsoft.com/en-us/library/ms144250(v=sql.105).aspx

(а) Чтобы проверить сопоставление экземпляров

select serverproperty('collation')

(b) Чтобы проверить сопоставление базы данных

select databasepropertyex('databasename', 'collation') sqlcollation

(c) Чтобы создать базу данных с использованием другого сопоставления

create database exampledatabase
collate sql_latin1_general_cp1_cs_as 

(d) Чтобы создать столбец с использованием другого сопоставления

create table exampletable (
    examplecolumn varchar(10) collate sql_latin1_general_cp1_ci_as null
)

(e) Чтобы изменить параметры сортировки столбцов

alter table exampletable
alter column examplecolumn varchar(10) collate sql_latin1_general_cp1_ci_as null

Можно изменить параметры сортировки экземпляра и базы данных, но это не влияет на ранее созданные объекты.

Также можно изменить сортировку столбцов на лету для сравнения строк, но это крайне не рекомендуется в производственной среде, поскольку это чрезвычайно дорого.

select
  column1 collate sql_latin1_general_cp1_ci_as as column1
from table1

5
Кажется, что диапазон символов вроде [A-Z]всегда нечувствителен к регистру. [ABCDEFGHIJKLMNOPQRSŠTUVWXYZŽÅÄÖ]однако, похоже, подчиняется сопоставлению.
jumxozizi

1
Кроме того, вы можете запросить чувствительность к регистру конкретного столбца примерно так:select COLLATION_NAME, iif(cast(COLLATIONPROPERTY(COLLATION_NAME, 'ComparisonStyle') as int) & 1 = 0, 'case sensitive', 'case insensitive') from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'exampletable' and COLUMN_NAME = 'examplecolumn'
Jeppe Stig Nielsen

@jumxozizi Я добавил ваше предложение к ответу.
Джон Заброски

@JeppeStigNielsen Я добавил ваше предложение к ответу.
Джон Заброски

18

Все эти разговоры о сопоставлении кажутся слишком сложными. Почему бы просто не использовать что-то вроде:

IF UPPER(@@VERSION) NOT LIKE '%AZURE%'

Тогда ваш чек нечувствителен к регистру независимо от сортировки


10
Потому что это несерьезно. В вашем примере используется переменная и начальный подстановочный знак. Но против столбца, проиндексированного с помощью сортировки без учета регистра, like 'a%'можно использовать индекс, а upperверсия - нет.
Мартин Смит

3
Вопрос заключался в том, likeчувствителен ли оператор к регистру.
jumxozizi

Вам нужно знать параметры сортировки, иначе это будет бессмысленно. Например, если запрашиваемый столбец не использует Latin1_General_CI_AS, то выполнение UPPER(@@VALUE) NOT LIKE '%SOMETHING%'или не @@COLUMN NOT LIKE '%SOMETHING%'имеет значения: результат будет таким же.
rsenna

13

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

CREATE TABLE Test (
    CI_Str VARCHAR(15) COLLATE Latin1_General_CI_AS -- Case-insensitive
,   CS_Str VARCHAR(15) COLLATE Latin1_General_CS_AS -- Case-sensitive
);

Вот быстрая демонстрация sqlfiddle, показывающая результаты порядка сортировки при поиске с LIKE.


12

Если вы хотите добиться поиска с учетом регистра без изменения сопоставления столбца / базы данных / сервера, вы всегда можете использовать это COLLATEпредложение, например

USE tempdb;
GO
CREATE TABLE dbo.foo(bar VARCHAR(32) COLLATE Latin1_General_CS_AS);
GO
INSERT dbo.foo VALUES('John'),('john');
GO
SELECT bar FROM dbo.foo 
  WHERE bar LIKE 'j%';
-- 1 row

SELECT bar FROM dbo.foo 
  WHERE bar COLLATE Latin1_General_CI_AS LIKE 'j%';
-- 2 rows

GO    
DROP TABLE dbo.foo;

Работает и по-другому, если ваш столбец / база данных / сервер чувствителен к регистру и вам не нужен поиск с учетом регистра, например

USE tempdb;
GO
CREATE TABLE dbo.foo(bar VARCHAR(32) COLLATE Latin1_General_CI_AS);
GO
INSERT dbo.foo VALUES('John'),('john');
GO
SELECT bar FROM dbo.foo 
  WHERE bar LIKE 'j%';
-- 2 rows

SELECT bar FROM dbo.foo 
  WHERE bar COLLATE Latin1_General_CS_AS LIKE 'j%';
-- 1 row

GO
DROP TABLE dbo.foo;

Будьте осторожны в последнем запросе, если вы WHERE bar COLLATE Latin1_General_CS_AS LIKE '[j-k]%'его используете, он вернет, так Johnкак в этом сопоставлении заглавные Jбуквы находятся между нижним jи нижним регистрами k. Это вроде aAbBcC...jJkKlLmM...чего не очевидно. Это кажется Latin1_General_BINболее предсказуемым с поиском по диапазону с оператором LIKE.
wqw

7

likeОператор принимает две строки. Эти строки должны иметь совместимые сопоставления, что объясняется здесь .

На мой взгляд, тогда все усложняется. Следующий запрос возвращает ошибку о том, что сопоставления несовместимы:

select *
from INFORMATION_SCHEMA.TABLES
where 'abc' COLLATE SQL_Latin1_General_CP1_CI_AS like 'ABC' COLLATE SQL_Latin1_General_CP1_CS_AS

Здесь на случайной машине сортировка по умолчанию SQL_Latin1_General_CP1_CI_AS. Следующий запрос выполнен успешно, но не возвращает строк:

select *
from INFORMATION_SCHEMA.TABLES
where 'abc' like 'ABC' COLLATE SQL_Latin1_General_CP1_CS_AS

Значения «abc» и «ABC» не совпадают в мире с учетом регистра.

Другими словами, существует разница между отсутствием сопоставления и использованием сопоставления по умолчанию. Когда на одной стороне нет сопоставления, тогда ей «назначается» явное сопоставление с другой стороны.

(Результаты будут такими же, когда явное сопоставление находится слева.)


Можете ли вы воспроизвести ошибку для таблицы, которая НЕ является системным объектом, например INFORMATION_SCHEMA.TABLES?
Аарон Бертран,

@AaronBertrand. . . Да, я могу. База данных битая;)?
Гордон Линофф

Не знаю, сейчас я использую мобильное устройство и не могу развернуть виртуальную машину Windows. Я просто не уверен, что все ваше описание технически верно.
Аарон Бертран,

4

Попробуйте бежать,

SELECT SERVERPROPERTY('COLLATION')

Затем выясните, чувствительны ли ваши параметры сортировки к регистру или нет.



0

Вы можете легко изменить параметры сортировки в Microsoft SQL Server Management Studio.

  • щелкните правой кнопкой мыши таблицу -> дизайн.
  • выберите свой столбец, прокрутите вниз свойства столбца до параметра «Сортировка».
  • Задайте предпочтения сортировки, отметив "С учетом регистра"
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.