Eu tenho uma tabela com uma chave exclusiva que inclui uma NVARCHAR(50)
coluna (correta ou não, mas existe). Então, ao tentar inserir Șc
ou C
(não importa a ordem da inserção) ele quebra na 2ª inserção devido a problemas de agrupamento. Aqui está o erro:
(1 linha(s) afetada) Msg 2601, Level 14, State 1, Line 16 Não é possível inserir linha de chave duplicada no objeto 'dbo.testT' com índice exclusivo 'IX_TestT'. O valor da chave duplicada é (C).
Selecione retornos:
O agrupamento padrão do banco de dados é Latin1_General_CI_AS
. Passei algum tempo procurando como resolver, sem alterar muito a estrutura já existente, mas não consigo encontrar uma maneira de começar a funcionar. Tentei diferentes agrupamentos e combinações, tudo falha. Leia ( aqui e aqui ) sobre expansões de personagens e assim por diante, ainda travado. Aqui está um código de exemplo que estou usando para replicar o problema, sinta-se à vontade para modificar e recomendar qualquer coisa que possa ajudar a resolver isso.
CREATE TABLE testT (
[Default_Collation] [NVARCHAR] (50) COLLATE DATABASE_DEFAULT,
[Latin1_General_CI_AS] [NVARCHAR] (50) COLLATE Latin1_General_CI_AS,
[Latin1_General_CI_AI] [NVARCHAR] (50) COLLATE Latin1_General_CI_AI,
[SQL_Collation] [NVARCHAR] (50) COLLATE SQL_Latin1_General_CP1_CI_AS);
CREATE UNIQUE CLUSTERED INDEX [IX_TestT] ON [dbo].[testT] ([Default_Collation])
ON [PRIMARY]
GO
INSERT INTO testT
SELECT N'Șc', --COLLATE Latin1_General_CI_AS
N'Șc', --COLLATE Latin1_General_CI_AS
N'Șc', --COLLATE Latin1_General_CI_AS
N'Șc' --COLLATE Latin1_General_CI_AS
INSERT INTO testT
SELECT N'C' --COLLATE Latin1_General_CI_AS
,N'C' --COLLATE Latin1_General_CI_AS
,N'C' --COLLATE Latin1_General_CI_AS
,N'C' --COLLATE SQL_Latin1_General_CP1_CI_AS
SELECT * FROM testT;
DROP TABLE testT;
O problema é que o antigo SQL Server Collations (ou seja, aqueles com nomes começando com
SQL_
) e as duas primeiras versões do Windows Collations (a80
série que veio com o SQL Server 2000 e não tem um número de versão no nome, e a90
série que veio com o SQL Server 2005) estão faltando os pesos de classificação para muitos caracteres. Isso foi corrigido principalmente a partir da100
série Collations que acompanha o SQL Server 2008.Como você pode ver nos exemplos abaixo, o
Ș
caractere corresponde a uma string vazia ao usar agrupamentos não binários, versão 80 ou 90 (e agrupamentos do SQL Server), pois ambos têm o mesmo peso de classificação: 0. Nada. Nada. Isso significa que ao compararN'Șc'
comN'C'
(usando pré-série 100 Collations), você está realmente comparandoN'c'
comN'C'
(teste nº 1):Então, infelizmente, você precisará descartar o PK, alterar a coluna para ter um Collation de 100 níveis (por exemplo
Latin1_General_100_CI_AS_SC
, ) e, em seguida, recriar o PK. Observe que a diferença entre o Collation sugerido e o Collation atual é o100
e o_SC
no final, o que permite que ele manipule corretamente os caracteres suplementares.Isso não significa que você precisa:
NVARCHAR
PK)table.column = N'Ș'
e@variable = N'Ș'
já que variáveis e literais de string usam o Collation padrão do banco de dados.Para obter mais exemplos desse comportamento, consulte a seção "Caracteres suplementares" da seguinte postagem do meu blog:
O Uni-Code: A busca pela lista verdadeira de caracteres válidos para identificadores T-SQL, parte 3 de 2 (identificadores delimitados)