Problème :
Cause :la colonne "Nom" contient un élément insensible à la casse (CI
) classement.
Solution :Vous devez utiliser un CS
collation :SELECT * FROM fn_helpcollations() WHERE description LIKE N'%case-sensitive%'
.
Remarque :Il existe un classement de base de données et un classement au niveau des colonnes. Et, il y a aussi un classement au niveau du serveur.
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
*/
Changer simplement le classement de la base de données ne sera PAS modifier le classement des tables et colonnes utilisateur existantes :
Après modification du classement de la base de données , le résultat des requêtes ci-dessus sera :
/*
DatabaseCollation -- changed
----------------------------
SQL_Latin1_General_CP1_CS_AS
*/
/*
ColumnCollation -- no change
----------------------------
SQL_Latin1_General_CP1_CI_AS
*/
et, comme vous pouvez le voir, le classement de la colonne Name
reste CI.
De plus, la modification du classement de la base de données n'affectera que les nouvelles tables et colonnes créées. Ainsi, la modification du classement de la base de données pourrait générer des résultats étranges (à mon opinion ) car certains [N][VAR]CHAR
les colonnes seront CI et les nouvelles colonnes seront CS.
Solution détaillée #1 :si seulement quelques requêtes pour la colonne Name
doit être CS
alors je vais réécrire WHERE
clause de ces requêtes :
SELECT Name
FROM dbo.Table_2
WHERE Name LIKE 'Joe' AND Name LIKE 'Joe' COLLATE SQL_Latin1_General_CP1_CS_AS
Cela donnera un changement à SQL Server pour faire une Index Seek
sur la colonne Name
(il y a un index sur la colonne Name
). De plus, le plan d'exécution inclura une conversion implicite (voir Predicate
propriété pour Index Seek
) en raison du prédicat suivant Name = N'Joe' COLLATE SQL_Latin1_General_CP1_CS_AS
.
Solution détaillée n° 2 :si toutes les requêtes portent sur la colonne Name
besoin d'être CS alors je changerai le classement uniquement pour la colonne Name
donc :
-- 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'