Um dia desses tive um problema para alterar o collate de um banco de dados aqui da empresa. Vou demonstrar o cenário que eu possuía e como consegui resolver o problema.
Collation é uma propriedade que define como o SQL Server irá interpretar caracteres, validando acentuação ou não, caracteres maiúsculos e minúsculos, etc.
Para obtermos uma descrição dos collates podemos consultar a function fn_helpcollations, conforme abaixo:
SELECT name, description FROM sys.fn_helpcollations()
Para realização do teste eu vou criar um banco de dados com um collate que distingue caracteres maiúsculos de minúsculos, confirmo a configuração escolhida. Na sequência vou criar dois objetos (procedures) com o mesmo nome, entretanto com case diferente.
-- Criação do Banco de Dados de exemplo CREATE DATABASE CollateTest_db COLLATE Latin1_General_BIN; USE CollateTest_db; -- Validando a configuração do banco SELECT database_id, name, collation_name FROM sys.databases WHERE DB_NAME(database_id) = 'CollateTest_db' -- Criação das procedures para os testes CREATE PROCEDURE retornadata_sp AS SELECT GETDATE(); CREATE PROCEDURE RetornaData_SP AS SELECT GETDATE(); -- Validando os objetos criados SELECT * FROM sys.objects WHERE type = 'P'
Até aqui, tudo bem. O banco de dados foi criado normalmente e foi possível criar dois objetos com o mesmo nome mas com cases diferentes, de acordo com a configuração escolhida para o collate.
O problema ocorre quando eu tento alterar o collate deste banco para um collate que NÃO considera o case dos caracteres. Neste caso, para o banco de dados, minhas duas procedures seriam o mesmo objeto. Para gerar o erro foi executado o seguinte script:
-- Tentativa de alteração do collate ALTER DATABASE CollateTest_db COLLATE SQL_Latin1_General_CP1_CI_AI
E o erro gerado foi este:
Msg 1505, Level 16, State 1, Line 1 The CREATE UNIQUE INDEX statement terminated because a duplicate key was found for the object name 'sys.sysschobjs' and the index name 'nc1'. The duplicate key value is (0, 1, RetornaData_SP). Msg 5072, Level 16, State 1, Line 1 ALTER DATABASE failed. The default collation of database 'CollateTest_db' cannot be set to SQL_Latin1_General_CP1_CI_AI. The statement has been terminated.
Se você tentar fazer um SELECT na tabela em questão (sys.sysschobjs) você receberá o seguinte erro:
Msg 208, Level 16, State 1, Line 1 Invalid object name 'sys.sysschobjs'.
Isto ocorre pois é uma tabela de sistema com acesso restrito. Entretanto nós conseguimos analisar os índices desta tabela executando a procedure sp_helpindex:
-- Validando o índice da tabela que ocorreu o erro SP_HELPINDEX [sys.sysschobjs]
Afinal de contas, como o problema foi resolvido?!? Depois de identificado que haviam objetos ondes seus nomes iriam conflitar com o Collate escolhido, percebemos que os objetos “duplicados” eram desnecessários. Apagamos os objetos do banco e com esta ação conseguimos realizar a alteração do collate do banco de dados.
Espero que a dica seja útil. Até mais!