Tout d'abord, des excuses pour une réponse aussi longue, car je pense qu'il y a toujours beaucoup de confusion lorsque les gens parlent de termes tels que le classement, l'ordre de tri, la page de code, etc.
De BOL :
Les classements dans SQL Server fournissent des règles de tri, des casse et des propriétés de sensibilité d'accent pour vos données . Les classements utilisés avec les types de données de caractères tels que char et varchar dictent la page de codes et les caractères correspondants qui peuvent être représentés pour ce type de données. Que vous installiez une nouvelle instance de SQL Server, restauriez une sauvegarde de base de données ou connectiez le serveur à des bases de données clientes, il est important que vous compreniez les exigences locales, l'ordre de tri et la sensibilité à la casse et à l'accentuation des données avec lesquelles vous travaillerez. .
Cela signifie que le classement est très important car il spécifie des règles sur la façon dont les chaînes de caractères des données sont triées et comparées.
Remarque: Plus d'informations sur COLLATIONPROPERTY
Maintenant, comprenons d'abord les différences ......
Sous T-SQL:
SELECT *
FROM::fn_helpcollations()
WHERE NAME IN (
'SQL_Latin1_General_CP1_CI_AS'
,'Latin1_General_CI_AS'
)
GO
SELECT 'SQL_Latin1_General_CP1_CI_AS' AS 'Collation'
,COLLATIONPROPERTY('SQL_Latin1_General_CP1_CI_AS', 'CodePage') AS 'CodePage'
,COLLATIONPROPERTY('SQL_Latin1_General_CP1_CI_AS', 'LCID') AS 'LCID'
,COLLATIONPROPERTY('SQL_Latin1_General_CP1_CI_AS', 'ComparisonStyle') AS 'ComparisonStyle'
,COLLATIONPROPERTY('SQL_Latin1_General_CP1_CI_AS', 'Version') AS 'Version'
UNION ALL
SELECT 'Latin1_General_CI_AS' AS 'Collation'
,COLLATIONPROPERTY('Latin1_General_CI_AS', 'CodePage') AS 'CodePage'
,COLLATIONPROPERTY('Latin1_General_CI_AS', 'LCID') AS 'LCID'
,COLLATIONPROPERTY('Latin1_General_CI_AS', 'ComparisonStyle') AS 'ComparisonStyle'
,COLLATIONPROPERTY('Latin1_General_CI_AS', 'Version') AS 'Version'
GO
Les résultats seraient:
En regardant les résultats ci-dessus, la seule différence est l'ordre de tri entre les 2 classements, mais ce n'est pas vrai, ce que vous pouvez voir comme ci-dessous:
Test 1:
--Clean up previous query
IF OBJECT_ID('Table_Latin1_General_CI_AS') IS NOT NULL
DROP TABLE Table_Latin1_General_CI_AS;
IF OBJECT_ID('Table_SQL_Latin1_General_CP1_CI_AS') IS NOT NULL
DROP TABLE Table_SQL_Latin1_General_CP1_CI_AS;
-- Create a table using collation Latin1_General_CI_AS
CREATE TABLE Table_Latin1_General_CI_AS (
ID INT IDENTITY(1, 1)
,Comments VARCHAR(50) COLLATE Latin1_General_CI_AS
)
-- add some data to it
INSERT INTO Table_Latin1_General_CI_AS (Comments)
VALUES ('kin_test1')
INSERT INTO Table_Latin1_General_CI_AS (Comments)
VALUES ('Kin_Tester1')
-- Create second table using collation SQL_Latin1_General_CP1_CI_AS
CREATE TABLE Table_SQL_Latin1_General_CP1_CI_AS (
ID INT IDENTITY(1, 1)
,Comments VARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS
)
-- add some data to it
INSERT INTO Table_SQL_Latin1_General_CP1_CI_AS (Comments)
VALUES ('kin_test1')
INSERT INTO Table_SQL_Latin1_General_CP1_CI_AS (Comments)
VALUES ('Kin_Tester1')
--Now try to join both tables
SELECT *
FROM Table_Latin1_General_CI_AS LG
INNER JOIN Table_SQL_Latin1_General_CP1_CI_AS SLG ON LG.Comments = SLG.Comments
GO
Résultats du test 1:
Msg 468, Level 16, State 9, Line 35
Cannot resolve the collation conflict between "SQL_Latin1_General_CP1_CI_AS" and "Latin1_General_CI_AS" in the equal to operation.
D'après les résultats ci-dessus, nous pouvons voir que nous ne pouvons pas comparer directement les valeurs sur des colonnes avec des classements différents, vous devez utiliser COLLATE
pour comparer les valeurs des colonnes.
TEST 2:
La principale différence est la performance, comme le souligne Erland Sommarskog lors de cette discussion sur msdn .
--Clean up previous query
IF OBJECT_ID('Table_Latin1_General_CI_AS') IS NOT NULL
DROP TABLE Table_Latin1_General_CI_AS;
IF OBJECT_ID('Table_SQL_Latin1_General_CP1_CI_AS') IS NOT NULL
DROP TABLE Table_SQL_Latin1_General_CP1_CI_AS;
-- Create a table using collation Latin1_General_CI_AS
CREATE TABLE Table_Latin1_General_CI_AS (
ID INT IDENTITY(1, 1)
,Comments VARCHAR(50) COLLATE Latin1_General_CI_AS
)
-- add some data to it
INSERT INTO Table_Latin1_General_CI_AS (Comments)
VALUES ('kin_test1')
INSERT INTO Table_Latin1_General_CI_AS (Comments)
VALUES ('kin_tester1')
-- Create second table using collation SQL_Latin1_General_CP1_CI_AS
CREATE TABLE Table_SQL_Latin1_General_CP1_CI_AS (
ID INT IDENTITY(1, 1)
,Comments VARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS
)
-- add some data to it
INSERT INTO Table_SQL_Latin1_General_CP1_CI_AS (Comments)
VALUES ('kin_test1')
INSERT INTO Table_SQL_Latin1_General_CP1_CI_AS (Comments)
VALUES ('kin_tester1')
--- Créer des index sur les deux tables
CREATE INDEX IX_LG_Comments ON Table_Latin1_General_CI_AS(Comments)
go
CREATE INDEX IX_SLG_Comments ON Table_SQL_Latin1_General_CP1_CI_AS(Comments)
--- Exécutez les requêtes
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_Latin1_General_CI_AS WHERE Comments = 'kin_test1'
GO
--- Cela aura une conversion IMPLICITE
--- Exécutez les requêtes
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_SQL_Latin1_General_CP1_CI_AS WHERE Comments = 'kin_test1'
GO
--- Cela n'aura PAS de conversion IMPLICITE
La raison de la conversion implicite est parce que j'ai mon classement de base de données et de serveur au fur SQL_Latin1_General_CP1_CI_AS
et à mesure que la table Table_Latin1_General_CI_AS a des commentaires de colonne définis comme VARCHAR(50)
avec COLLATE Latin1_General_CI_AS , donc pendant la recherche, SQL Server doit effectuer une conversion IMPLICIT.
Test 3:
Avec la même configuration, nous allons maintenant comparer les colonnes varchar avec les valeurs nvarchar pour voir les changements dans les plans d'exécution.
- exécuter la requête
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_Latin1_General_CI_AS WHERE Comments = (SELECT N'kin_test1' COLLATE Latin1_General_CI_AS)
GO
- exécuter la requête
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_SQL_Latin1_General_CP1_CI_AS WHERE Comments = N'kin_test1'
GO
Notez que la première requête peut effectuer une recherche d'index mais doit effectuer une conversion implicite tandis que la seconde effectue une analyse d'index qui s'avère inefficace en termes de performances lorsqu'elle analysera de grandes tables.
Conclusion :
- Tous les tests ci-dessus montrent qu'il est très important d'avoir un bon classement pour votre instance de serveur de base de données.
SQL_Latin1_General_CP1_CI_AS
est un classement SQL avec les règles qui vous permettent de trier les données pour unicode et non-unicode sont différentes.
- Le classement SQL ne pourra pas utiliser Index lors de la comparaison de données unicode et non-unicode, comme indiqué dans les tests ci-dessus, lors de la comparaison de données nvarchar avec des données varchar, il analyse Index et ne recherche pas.
Latin1_General_CI_AS
est un classement Windows avec les règles qui vous permettent de trier les données pour unicode et non-unicode sont les mêmes.
- Le classement Windows peut toujours utiliser Index (recherche d'index dans l'exemple ci-dessus) lors de la comparaison de données unicode et non unicode, mais vous voyez une légère baisse des performances.
- Je recommande vivement de lire la réponse d'Erland Sommarskog + les éléments de connexion qu'il a pointés.
Cela me permettra de ne pas avoir de problèmes avec les tables #temp, mais y a-t-il des pièges?
Voir ma réponse ci-dessus.
Aurais-je perdu des fonctionnalités ou des fonctionnalités de toute nature en n'utilisant pas un classement «actuel» de SQL 2008?
Tout dépend des fonctionnalités / fonctionnalités auxquelles vous faites référence. Le classement consiste à stocker et à trier des données.
Qu'en est-il lorsque nous passons (par exemple dans 2 ans) de 2008 à SQL 2012? Vais-je avoir des problèmes alors? Serais-je obligé à un moment donné d'aller à Latin1_General_CI_AS?
Je ne peux pas me porter garant! Comme les choses pourraient changer et qu'il est toujours bon d'être en accord avec la suggestion de Microsoft +, vous devez comprendre vos données et les pièges que j'ai mentionnés ci-dessus. Référez-vous également à ceci et à ces éléments de connexion.
J'ai lu que certains scripts DBA complètent les lignes de bases de données complètes, puis exécutez le script d'insertion dans la base de données avec le nouveau classement - j'ai très peur et méfiez-vous de cela - recommanderiez-vous de faire cela?
Lorsque vous souhaitez modifier le classement, ces scripts sont utiles. Je me suis retrouvé à changer le classement des bases de données pour correspondre au classement du serveur plusieurs fois et j'ai quelques scripts qui le font assez bien. Faites-moi savoir si vous en avez besoin.
Les références :