В документации о LIKE-операторе ничего не сказано о чувствительности к регистру. Это? Как включить/отключить его?
Я запрашиваю столбцы varchar(n)
на SQL Server 2005, если это имеет значение.
В документации о LIKE-операторе ничего не сказано о чувствительности к регистру. Это? Как включить/отключить его?
Я запрашиваю столбцы varchar(n)
на SQL Server 2005, если это имеет значение.
Это не тот оператор, который чувствителен к регистру, это сам столбец.
Когда выполняется установка 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
У вас есть возможность определить порядок сортировки во время определения вашей таблицы. Если вы определяете регистр, чувствительный к регистру, ваш оператор 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
.
Все эти разговоры о сопоставлении кажутся немного сложнее. Почему бы просто не использовать что-то вроде:
IF UPPER(@@VERSION) NOT LIKE '%AZURE%'
Тогда ваш чек нечувствителен к регистру, независимо от того, как сортировать
Если вы хотите добиться поиска с учетом регистра, не меняя сортировки столбца/базы данных/сервера, вы всегда можете использовать предложение 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;
Оператор 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.
Другими словами, существует разница между отсутствием сопоставления и использованием сопоставления по умолчанию. Когда одна сторона не имеет сопоставления, тогда она "назначает" явное сопоставление с другой стороны.
(Результаты одинаковы, когда явная сортировка слева).
Попробуйте запустить
SELECT SERVERPROPERTY('COLLATION')
Затем выясните, является ли ваша сортировка чувствительной к регистру или нет.