Problema:
Causa:la colonna "Nome" non fa distinzione tra maiuscole e minuscole (CI
) confronto.
Soluzione:devi usare un CS
confronto:SELECT * FROM fn_helpcollations() WHERE description LIKE N'%case-sensitive%'
.
Nota:esistono regole di confronto database e regole di confronto a livello di colonna. E c'è anche un confronto a livello di server.
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
*/
La semplice modifica delle regole di confronto del database NON cambia le regole di confronto per le tabelle e le colonne utente esistenti:
Dopo la modifica delle regole di confronto del database , l'output delle query precedenti sarà:
/*
DatabaseCollation -- changed
----------------------------
SQL_Latin1_General_CP1_CS_AS
*/
/*
ColumnCollation -- no change
----------------------------
SQL_Latin1_General_CP1_CI_AS
*/
e, come puoi vedere, le regole di confronto della colonna Name
rimane CI.
Inoltre, la modifica delle regole di confronto del database influirà solo sulle nuove tabelle e colonne create. Pertanto, la modifica delle regole di confronto del database potrebbe generare risultati strani (a mio opinione ) perché alcuni [N][VAR]CHAR
le colonne saranno CI e le nuove colonne saranno CS.
Soluzione dettagliata n. 1:se solo alcune query per la colonna Name
deve essere CS
quindi riscriverò WHERE
clausola di queste query così:
SELECT Name
FROM dbo.Table_2
WHERE Name LIKE 'Joe' AND Name LIKE 'Joe' COLLATE SQL_Latin1_General_CP1_CS_AS
Questo darà una modifica a SQL Server per eseguire una Index Seek
nella colonna Name
(in c'è un indice sulla colonna Name
). Inoltre, il piano di esecuzione includerà una conversione implicita (vedi Predicate
proprietà per Index Seek
) a causa del seguente predicato Name = N'Joe' COLLATE SQL_Latin1_General_CP1_CS_AS
.
Soluzione dettagliata n. 2:se tutte le query per la colonna Name
deve essere CS, quindi cambierò le regole di confronto solo per la colonna Name
quindi:
-- 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'