Является ли оператор LIKE чувствительным к регистру с сервером MS SQL?

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

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

Ответ 1

Это не тот оператор, который чувствителен к регистру, это сам столбец.

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

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

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

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

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

Ответ 2

У вас есть возможность определить порядок сортировки во время определения вашей таблицы. Если вы определяете регистр, чувствительный к регистру, ваш оператор 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.

Ответ 3

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

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

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

Ответ 4

Если вы хотите добиться поиска с учетом регистра, не меняя сортировки столбца/базы данных/сервера, вы всегда можете использовать предложение 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;

Ответ 5

Оператор 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" не совпадают в мире case-sensitve.

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

(Результаты одинаковы, когда явная сортировка слева).

Ответ 6

Попробуйте запустить

SELECT SERVERPROPERTY('COLLATION')

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