Antes de tudo, peço desculpas por uma resposta tão longa, pois sinto que ainda há muita confusão quando as pessoas falam sobre termos como agrupamento, ordem de classificação, página de código etc.
De BOL :
Os agrupamentos no SQL Server fornecem regras de classificação, maiúsculas e minúsculas propriedades de sensibilidade aos seus dados . Os agrupamentos usados com tipos de dados de caracteres, como char e varchar, determinam a página de código e os caracteres correspondentes que podem ser representados para esse tipo de dados. Esteja você instalando uma nova instância do SQL Server, restaurando um backup do banco de dados ou conectando o servidor aos bancos de dados do cliente, é importante entender os requisitos de localidade, a ordem de classificação e a sensibilidade de maiúsculas e minúsculas dos dados com os quais você trabalhará .
Isso significa que o agrupamento é muito importante, pois especifica regras sobre como as seqüências de caracteres dos dados são classificadas e comparadas.
Nota: Mais informações sobre COLLATIONPROPERTY
Agora vamos primeiro entender as diferenças ......
Executando abaixo do 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
Os resultados seriam:
![insira a descrição da imagem aqui](https://i.stack.imgur.com/VvtpW.jpg)
Olhando para os resultados acima, a única diferença é a ordem de classificação entre os dois agrupamentos. Mas isso não é verdade, e você pode ver o motivo:
Teste 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
Resultados do Teste 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.
A partir dos resultados acima, podemos ver que, se não podemos comparar diretamente valores em colunas com diferentes agrupamentos, você deve usar COLLATE
para comparar os valores da coluna.
TESTE 2:
A principal diferença é o desempenho, como Erland Sommarskog aponta nesta discussão no 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')
--- Crie índices nas duas tabelas
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)
--- Execute as consultas
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_Latin1_General_CI_AS WHERE Comments = 'kin_test1'
GO
--- Isso terá conversão IMPLICIT
![insira a descrição da imagem aqui](https://i.stack.imgur.com/o6TsD.jpg)
--- Execute as consultas
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_SQL_Latin1_General_CP1_CI_AS WHERE Comments = 'kin_test1'
GO
--- Isso NÃO terá conversão IMPLICIT
![insira a descrição da imagem aqui](https://i.stack.imgur.com/Lhiu8.jpg)
A razão para a conversão implícita é porque, eu tenho meu banco de dados e servidor de agrupamento tanto como SQL_Latin1_General_CP1_CI_AS
ea tabela Table_Latin1_General_CI_AS tem coluna Comentários definidos como VARCHAR(50)
com COLLATE Latin1_General_CI_AS , por isso durante a pesquisa SQL Server tem que fazer uma conversão implícita.
Teste 3:
Com a mesma configuração, agora compararemos as colunas varchar com os valores nvarchar para ver as alterações nos planos de execução.
- execute a consulta
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_Latin1_General_CI_AS WHERE Comments = (SELECT N'kin_test1' COLLATE Latin1_General_CI_AS)
GO
![insira a descrição da imagem aqui](https://i.stack.imgur.com/ZYsbJ.jpg)
- execute a consulta
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_SQL_Latin1_General_CP1_CI_AS WHERE Comments = N'kin_test1'
GO
![insira a descrição da imagem aqui](https://i.stack.imgur.com/56BBC.jpg)
Observe que a primeira consulta é capaz de fazer a busca de índice, mas precisa fazer a conversão implícita, enquanto a segunda realiza uma varredura de índice que se mostra ineficiente em termos de desempenho, quando varre tabelas grandes.
Conclusão:
- Todos os testes acima mostram que ter o agrupamento correto é muito importante para a instância do servidor de banco de dados.
SQL_Latin1_General_CP1_CI_AS
é um agrupamento SQL com as regras que permitem classificar dados para unicode e não unicode são diferentes.
- O agrupamento SQL não poderá usar o Index ao comparar dados unicode e não unicode, como visto nos testes acima, que, ao comparar dados nvarchar com dados varchar, ele faz a varredura de índice e não procura.
Latin1_General_CI_AS
é um agrupamento do Windows com as regras que permitem classificar dados para unicode e não unicode.
- O agrupamento do Windows ainda pode usar o Índice (busca de índice no exemplo acima) ao comparar dados unicode e não unicode, mas você vê uma pequena penalidade no desempenho.
- É altamente recomendável ler a resposta de Erland Sommarskog + os itens de conexão que ele apontou.
Isso me permitirá não ter problemas com as #temp tables, mas existem armadilhas?
Veja minha resposta acima.
Perderia qualquer funcionalidade ou recurso de qualquer tipo ao não usar um agrupamento "atual" do SQL 2008?
Tudo depende de quais funcionalidades / recursos você está se referindo. Agrupar é armazenar e classificar dados.
E quando mudamos (por exemplo, em 2 anos) de 2008 para o SQL 2012? Terei problemas então? Em algum momento eu seria forçado a ir para Latin1_General_CI_AS?
Não posso garantir! Como as coisas podem mudar e é sempre bom estar alinhado com a sugestão da Microsoft +, você precisa entender seus dados e as armadilhas que mencionei acima. Consulte também este e este itens de conexão.
Li que alguns scripts do DBA concluem as linhas de bancos de dados completos e, em seguida, executam o script de inserção no banco de dados com o novo agrupamento - estou com muito medo e desconfiado disso - você recomendaria fazer isso?
Quando você deseja alterar o agrupamento, esses scripts são úteis. Eu me encontrei alterando o agrupamento de bancos de dados para coincidir com o agrupamento do servidor muitas vezes e eu tenho alguns scripts que o fazem muito bem. Deixe-me saber se você precisar.
Referências :