Prima di tutto, mi scuso per una risposta così lunga, poiché ritengo che ci sia ancora molta confusione quando le persone parlano di termini come fascicolazione, ordinamento, tabella codici, ecc.
Da BOL :
Le regole di confronto in SQL Server forniscono regole di ordinamento, case e proprietà di sensibilità dell'accento per i dati . Le regole di confronto utilizzate con tipi di dati carattere come char e varchar determinano la tabella codici e i caratteri corrispondenti che possono essere rappresentati per quel tipo di dati. Che si stia installando una nuova istanza di SQL Server, ripristinando un backup del database o collegando il server ai database client, è importante comprendere i requisiti della locale, l'ordinamento e la sensibilità di maiuscolo e minuscolo dei dati con cui si lavorerà .
Ciò significa che le regole di confronto sono molto importanti in quanto specificano le regole su come ordinare e confrontare le stringhe di caratteri dei dati.
Nota: maggiori informazioni su COLLATIONPROPERTY
Ora vediamo prima le differenze ......
In esecuzione sotto 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
I risultati sarebbero:
Guardando i risultati sopra, l'unica differenza è l'ordinamento tra le 2 regole di confronto, ma questo non è vero, che puoi vedere perché come di seguito:
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
Risultati del 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.
Dai risultati precedenti possiamo vedere che non possiamo confrontare direttamente i valori su colonne con diverse regole di confronto, che devi usare COLLATE
per confrontare i valori di colonna.
TEST 2:
La differenza principale è la prestazione, come sottolinea Erland Sommarskog in questa discussione su 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')
--- Crea indici su entrambe le tabelle
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)
--- Esegui le query
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_Latin1_General_CI_AS WHERE Comments = 'kin_test1'
GO
--- Questo avrà una conversione IMPLICIT
--- Esegui le query
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_SQL_Latin1_General_CP1_CI_AS WHERE Comments = 'kin_test1'
GO
--- Questo NON avrà conversione IMPLICIT
Il motivo della conversione implicita è perché, ho il mio database e le regole di confronto del server sia come SQL_Latin1_General_CP1_CI_AS
che nella tabella Table_Latin1_General_CI_AS ha i commenti di colonna definiti come VARCHAR(50)
con COLLATE Latin1_General_CI_AS , quindi durante la ricerca SQL Server deve eseguire una conversione IMPLICIT.
Test 3:
Con la stessa configurazione, ora confronteremo le colonne varchar con i valori di nvarchar per vedere le modifiche nei piani di esecuzione.
- esegui la query
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_Latin1_General_CI_AS WHERE Comments = (SELECT N'kin_test1' COLLATE Latin1_General_CI_AS)
GO
- esegui la query
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_SQL_Latin1_General_CP1_CI_AS WHERE Comments = N'kin_test1'
GO
Si noti che la prima query è in grado di eseguire la ricerca dell'Indice ma deve eseguire la conversione implicita mentre la seconda esegue una scansione dell'Indice che si rivela inefficiente in termini di prestazioni quando eseguirà la scansione di tabelle di grandi dimensioni.
Conclusione :
- Tutti i test sopra riportati mostrano che avere regole di confronto corrette è molto importante per l'istanza del server di database.
SQL_Latin1_General_CP1_CI_AS
è un confronto SQL con le regole che consentono di ordinare i dati per Unicode e Non Unicode sono diversi.
- Le regole di confronto SQL non saranno in grado di utilizzare l'Indice quando si confrontano i dati unicode e non unicode come visto nei test precedenti che, confrontando i dati nvarchar con i dati varchar, esegue la scansione dell'indice e non la ricerca.
Latin1_General_CI_AS
è un confronto di Windows con le regole che consentono di ordinare i dati per Unicode e Non Unicode.
- Le regole di confronto di Windows possono comunque utilizzare Index (indice di ricerca nell'esempio sopra) quando si confrontano i dati unicode e non unicode ma si nota una leggera penalità delle prestazioni.
- Consiglio vivamente di leggere la risposta Erland Sommarskog + gli elementi di connessione che ha indicato.
Questo mi permetterà di non avere problemi con le tabelle #temp, ma ci sono insidie?
Vedi la mia risposta sopra.
Vorrei perdere funzionalità o caratteristiche di qualsiasi tipo non utilizzando una raccolta "corrente" di SQL 2008?
Tutto dipende da quale funzionalità / caratteristiche ti riferisci. Le regole di confronto stanno archiviando e ordinando i dati.
Che dire di quando ci spostiamo (ad esempio tra 2 anni) dal 2008 a SQL 2012? Avrò problemi allora? A un certo punto sarei costretto ad andare su Latin1_General_CI_AS?
Non posso garantire! Poiché le cose potrebbero cambiare ed è sempre bene essere in linea con il suggerimento di Microsoft + devi capire i tuoi dati e le insidie che ho menzionato sopra. Vedere anche questo e questo gli elementi di connessione.
Ho letto che alcuni script di DBA completano le righe di database completi e quindi eseguono lo script di inserimento nel database con la nuova raccolta - sono molto spaventato e diffidente di questo - consiglieresti di farlo?
Quando si desidera modificare le regole di confronto, tali script sono utili. Mi sono ritrovato a cambiare le regole di confronto dei database in modo che corrispondano più volte alle regole di confronto dei server e ho alcuni script che lo rendono abbastanza accurato. Fammi sapere se ne hai bisogno.
Riferimenti :