Чи чутливий оператор LIKE до регістру MSSQL Server?


99

У документації про оператора LIKE нічого не сказано про чутливість до регістру. Є це? Як його ввімкнути / вимкнути?

Я запитую varchar(n)стовпці щодо інсталяції Microsoft SQL Server 2005, якщо це має значення.


14
Це залежить від сортування вашого стовпця (або бази даних). Якщо він чутливий до регістру, тоді LIKEчутливий до регістру, якщо це не так, то LIKEнемає
Ламак

Перевірте документацію про порівняння SQL-сервера 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.

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