ตัวดำเนินการ LIKE คำนึงถึงขนาดตัวพิมพ์กับ MSSQL Server หรือไม่


101

ในเอกสารเกี่ยวกับตัวดำเนินการ LIKEไม่มีอะไรบอกเกี่ยวกับกรณี - ไวของมัน ใช่ไหม? จะเปิด / ปิดได้อย่างไร?

ฉันกำลังสอบถามvarchar(n)คอลัมน์ในการติดตั้ง Microsoft SQL Server 2005 ถ้าเป็นเรื่องสำคัญ


14
ขึ้นอยู่กับการเรียงคอลัมน์ของคุณ (หรือฐานข้อมูล) ถ้าเป็นกรณีที่ละเอียดอ่อนก็LIKEจะพิจารณาตัวพิมพ์เล็กและตัวพิมพ์ใหญ่หากไม่ใช่แสดงว่าLIKEไม่ใช่
Lamak

ตรวจสอบเอกสารเกี่ยวกับ SQL-Server collations msdn.microsoft.com/en-us/library/ms144250%28v=sql.105%29.aspx
GarethD

เป้าหมายของคุณคืออะไร? คุณต้องการให้พิจารณาตัวพิมพ์เล็กและตัวพิมพ์ใหญ่หรือไม่?
Aaron Bertrand

1
ความไวของตัวพิมพ์มีค่าดีฟอลต์เป็นการเปรียบเทียบบนคอลัมน์ซึ่งค่าดีฟอลต์เป็นค่าบนฐานข้อมูล มันกลมเป็นส่วนใหญ่คุณอยากไปทางไหน?
Tony Hopkinson

คำตอบ:


106

ไม่ใช่ตัวดำเนินการที่พิจารณาตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ แต่เป็นคอลัมน์เอง

เมื่อทำการติดตั้ง SQL Server การเปรียบเทียบเริ่มต้นจะถูกเลือกให้กับอินสแตนซ์ เว้นแต่จะระบุไว้เป็นอย่างอื่นอย่างชัดเจน (ตรวจสอบ collate clause bellow) เมื่อสร้างฐานข้อมูลใหม่ฐานข้อมูลจะสืบทอดการเปรียบเทียบจากอินสแตนซ์และเมื่อสร้างคอลัมน์ใหม่จะสืบทอดการเรียงลำดับจากฐานข้อมูลที่เป็นเจ้าของ

การเปรียบเทียบเช่นsql_latin1_general_cp1_ci_asกำหนดวิธีการปฏิบัติต่อเนื้อหาของคอลัมน์ CI ย่อมาจาก case insensitive และ AS ย่อมาจาก accent sensitive

ดูรายการ collations ทั้งหมดได้ที่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
)

(จ) เพื่อแก้ไขการเรียงคอลัมน์

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

8
ดูเหมือนว่าช่วงของอักขระ[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 ฉันเพิ่มข้อเสนอแนะของคุณในคำตอบ
John Zabroski

@JeppeStigNielsen ฉันเพิ่มข้อเสนอแนะของคุณในคำตอบ
John Zabroski

21

การพูดคุยเกี่ยวกับการเรียงลำดับทั้งหมดนี้ดูเหมือนจะซับซ้อนเกินไป ทำไมไม่ใช้สิ่งที่ชอบ:

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

จากนั้นเช็คของคุณจะไม่คำนึงถึงขนาดตัวพิมพ์


11
เพราะสิ่งนี้ไม่สามารถถอดเปลี่ยนได้ ตัวอย่างของคุณใช้ตัวแปรและสัญลักษณ์นำหน้า แต่เมื่อเทียบกับคอลัมน์ที่จัดทำดัชนีด้วยการเปรียบเทียบแบบไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่like 'a%'อาจใช้ดัชนีและupperเวอร์ชันไม่สามารถทำได้
Martin Smith

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
);

นี่คือการสาธิตอย่างรวดเร็วใน sqlfiddleLIKEแสดงผลของคำสั่งเปรียบเทียบในการค้นหาด้วย


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 ได้หรือไม่
Aaron Bertrand

@AaronBertrand. . . ใช่ฉันทำได้. ฐานข้อมูลเสีย;)?
Gordon Linoff

ไม่ทราบตอนนี้ฉันใช้อุปกรณ์เคลื่อนที่และไม่สามารถหมุน Windows VM ได้ ฉันไม่รู้ว่าคำอธิบายทั้งหมดของคุณถูกต้องในทางเทคนิค
Aaron Bertrand

4

ลองวิ่ง

SELECT SERVERPROPERTY('COLLATION')

จากนั้นตรวจสอบว่าการเปรียบเทียบของคุณมีความละเอียดอ่อนหรือไม่



0

คุณสามารถเปลี่ยนการเปรียบเทียบใน Microsoft SQL Server Management studio ได้อย่างง่ายดาย

  • คลิกขวาที่ตาราง -> ออกแบบ
  • เลือกคอลัมน์ของคุณเลื่อนลง i คอลัมน์คุณสมบัติไปที่การเรียงลำดับ
  • ตั้งค่าการจัดเรียงของคุณโดยทำเครื่องหมายที่ "ตัวพิมพ์เล็กและใหญ่"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.