Problém:
Příčina:Ve sloupci 'Název' se nerozlišují velká a malá písmena (CI
) řazení.
Řešení:Musíte použít CS
řazení:SELECT * FROM fn_helpcollations() WHERE description LIKE N'%case-sensitive%'
.
Poznámka:Existuje řazení databáze a řazení na úrovni sloupce. A existuje také řazení na úrovni serveru.
SELECT DATABASEPROPERTYEX(DB_NAME(), 'Collation') AS DatabaseCollation
/*
-- Sample output (my database)
DatabaseCollation
----------------------------
SQL_Latin1_General_CP1_CI_AS
*/
SELECT col.collation_name AS ColumnCollation
FROM sys.columns col
WHERE col.object_id = OBJECT_ID(N'dbo.Table_2')
AND col.name = N'Name'
/*
-- Sample output (my database)
ColumnCollation
----------------------------
SQL_Latin1_General_CP1_CI_AS
*/
Pouhá změna řazení databáze NE změnit řazení pro existující uživatelské tabulky a sloupce:
Po změně řazení databáze , výstup výše uvedených dotazů bude:
/*
DatabaseCollation -- changed
----------------------------
SQL_Latin1_General_CP1_CS_AS
*/
/*
ColumnCollation -- no change
----------------------------
SQL_Latin1_General_CP1_CI_AS
*/
a jak můžete vidět řazení sloupce Name
zůstává CI.
Navíc změna řazení databází ovlivní pouze nově vytvořené tabulky a sloupce. Změna řazení databází by tedy mohla generovat podivné výsledky (podle mého názoru ), protože některé [N][VAR]CHAR
sloupce budou CI a nové sloupce budou CS.
Podrobné řešení č. 1:pokud jsou jen nějaké dotazy na sloupec Name
musí být CS
pak přepíšu WHERE
klauzule těchto dotazů takto:
SELECT Name
FROM dbo.Table_2
WHERE Name LIKE 'Joe' AND Name LIKE 'Joe' COLLATE SQL_Latin1_General_CP1_CS_AS
Tím se SQL Server změní na Index Seek
ve sloupci Name
(ve sloupci Name
je index ). Prováděcí plán bude také zahrnovat implicitní konverzi (viz Predicate
vlastnost pro Index Seek
) kvůli následujícímu predikátu Name = N'Joe' COLLATE SQL_Latin1_General_CP1_CS_AS
.
Podrobné řešení č. 2:pokud jsou všechny dotazy pro sloupec Name
musí být CS, pak změním řazení pouze pro sloupec Name
tedy:
-- Drop all objects that depends on this column (ex. indexes, constraints, defaults)
DROP INDEX IX_Table_2_Name ON dbo.Table_2
-- Change column's collation
ALTER TABLE dbo.Table_2
ALTER COLUMN Name VARCHAR(50) COLLATE SQL_Latin1_General_CP1_CS_AS
-- Replace VARCHAR(50) with proper data type and max. length
-- Replace COLLATE SQL_Latin1_General_CP1_CS_AS with the right CS collation
-- Recreate all objects that depends on column Name (ex. indexes, constraints, defaults)
CREATE INDEX IX_Table_2_Name ON dbo.Table_2 (Name)
-- Test query
SELECT Name
FROM dbo.Table_2
WHERE Name LIKE 'Joe'