Problema:
Causa:la columna 'Nombre' no distingue entre mayúsculas y minúsculas (CI
) colación.
Solución:Tienes que usar un CS
intercalación:SELECT * FROM fn_helpcollations() WHERE description LIKE N'%case-sensitive%'
.
Nota:Hay una intercalación de base de datos y una intercalación a nivel de columna. Y también hay una colación a nivel de servidor.
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
*/
Simplemente cambiar la intercalación de la base de datos NO cambie la intercalación de las tablas y columnas de usuario existentes:
Después de cambiar la intercalación de la base de datos , el resultado de las consultas anteriores será:
/*
DatabaseCollation -- changed
----------------------------
SQL_Latin1_General_CP1_CS_AS
*/
/*
ColumnCollation -- no change
----------------------------
SQL_Latin1_General_CP1_CI_AS
*/
y, como puede ver la intercalación de la columna Name
sigue siendo CI.
Además, cambiar la intercalación de la base de datos afectará solo a las nuevas tablas y columnas creadas. Por lo tanto, cambiar la intercalación de la base de datos podría generar resultados extraños (en mi opinión ) porque algunos [N][VAR]CHAR
las columnas serán CI y las nuevas columnas serán CS.
Solución detallada n. ° 1:si solo algunas consultas para la columna Name
necesita ser CS
luego reescribiré WHERE
cláusula de estas consultas así:
SELECT Name
FROM dbo.Table_2
WHERE Name LIKE 'Joe' AND Name LIKE 'Joe' COLLATE SQL_Latin1_General_CP1_CS_AS
Esto dará un cambio a SQL Server para hacer una Index Seek
en la columna Name
(hay un índice en la columna Name
). Además, el plan de ejecución incluirá una conversión implícita (ver Predicate
propiedad para Index Seek
) debido al siguiente predicado Name = N'Joe' COLLATE SQL_Latin1_General_CP1_CS_AS
.
Solución detallada #2:si todas las consultas para la columna Name
necesita ser CS, entonces cambiaré la intercalación solo para la columna Name
así:
-- 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'