Vendor saya mengharuskan database gudang data peka huruf besar-kecil, tetapi saya perlu melakukan kueri yang tidak peka huruf besar-kecil terhadapnya.
Dalam basis data case-sensitive, bagaimana Anda menulis ini menjadi case-insensitive?
Where Name like '%hospitalist%'
Anda dapat menambahkan kolasi baru ke kueri pilihan Anda untuk menemukan case sensitive atau insensitive.
-- Case sensitive example
SELECT *
FROM TABLE
WHERE Name collate SQL_Latin1_General_CP1_CS_AS like '%hospitalist%'
-- Case insensitive example
SELECT *
FROM TABLE
WHERE Name collate SQL_Latin1_General_CP1_CI_AS like '%hospitalist%'
Hanya saja, waspadai masalah kinerja yang dapat muncul. Anda perlu memindai indeks berkerumun untuk menyesuaikan / menemukan nilai saat Anda melakukan kolasi. Cara Anda menulis bagian LIKE
juga membuat kueri tidak dapat ditagih.
Saya mengambil trik collation dari kelas SELECT Seminar Kendra Little's. Anda dapat menemukan informasi kolasi tambahan dari Ben Snaidero dari MS SQL Tips..
Meskipun Anda dapat menggunakan fungsi skalar seperti UPPER atau LOWER dan Anda dapat menyatukan kembali kolom sehingga tidak lagi case sensitive, semua pendekatan ini memerlukan konversi data yang dilakukan terhadap data dasar yang tidak akan pernah memungkinkan pencarian indeks. Anda juga memimpin LIKE Anda dengan wildcard, jadi ini tidak terlalu menjadi perhatian Anda dalam skenario ini, tetapi jika Anda ingin mencari bagian kiri string dengan cara yang efisien DAN memungkinkan pengoptimal untuk mencari melalui indeks, Anda dapat menentukan string Anda dengan tanda kurung ([]) sebagai berikut:
SELECT *
FROM TABLE
WHERE Name LIKE '[hH][oO][sS][pP][iI][tT][aA][lL][iI][sS][tT]%'
Contoh ini (dbfiddle link here) lebih baik dalam menunjukkan apa yang saya maksud:
CREATE TABLE #tmp_cohellation_fun
(
ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
, myValue VARCHAR(50) COLLATE SQL_Latin1_General_CP1_CS_AS
)
-- Garbage values to represent data you don't want
INSERT INTO #tmp_cohellation_fun
SELECT CAST(NEWID() AS VARCHAR(50))
FROM master.sys.configurations t1
CROSS JOIN master.sys.configurations t2
CROSS JOIN master.sys.configurations t3;
-- Sprinkle a little bit of good data
INSERT INTO #tmp_cohellation_fun
(myValue)
VALUES ('Apple')
, ('apple')
-- Another healthy helping of garbage that we don't care about
INSERT INTO #tmp_cohellation_fun
SELECT CAST(NEWID() AS VARCHAR(50))
FROM master.sys.configurations t1
CROSS JOIN master.sys.configurations t2
CROSS JOIN master.sys.configurations t3;
-- Some more good data
INSERT INTO #tmp_cohellation_fun
(myValue)
VALUES
('aPple')
, ('APPLE')
, ('APple')
-- Final insert of garbage that we don't care about
INSERT INTO #tmp_cohellation_fun
SELECT CAST(NEWID() AS VARCHAR(50))
FROM master.sys.configurations t1
CROSS JOIN master.sys.configurations t2
CROSS JOIN master.sys.configurations t3
;
-- Create a nonclustered rowstore index
CREATE INDEX ix_myValue ON #tmp_cohellation_fun (myValue)
;
SET STATISTICS XML ON
;
-- Seek, but incorrect results
SELECT *
FROM #tmp_cohellation_fun
WHERE myValue LIKE 'apple%'
;
-- Scan, with correct results
SELECT *
FROM #tmp_cohellation_fun
WHERE myValue COLLATE SQL_Latin1_General_CP1_CI_AS LIKE 'apple%'
;
-- Seek, with correct results
SELECT *
FROM #tmp_cohellation_fun
WHERE myValue LIKE '[aA][pP][pP][lL][eE]%'
;
SET STATISTICS XML OFF
;
DROP TABLE IF EXISTS #tmp_cohellation_fun
Baik jawaban ini maupun jawaban COLLATE
akan mempengaruhi kinerja, karena keduanya membuat query non-SARGable, tetapi cara termudah untuk melakukannya (seperti yang disarankan Edgar dalam sebuah komentar) adalah:
WHERE LOWER(Name) LIKE '%hospitalist%'
atau
WHERE UPPER(Name) LIKE '%HOSPITALIST%'