Existe uma maneira mais fácil de resolver incompatibilidades de classificação do SQL Server / banco de dados do que alterar todas as colunas?

8

AVISO LEGAL: Eu sei que essa pergunta já foi feita centenas de vezes, mas eu só queria verificar se não havia uma solução mais fácil que eu poderia ter perdido antes de prosseguir e escrever / obter muitos códigos para fazer isso .

Nosso software usa um banco de dados que foi originalmente projetado para o SQL Server 7 e, como tal, todos os scripts que o criam não especificam nenhum agrupamento explícito para nenhuma coluna de caractere. Em vez disso, quando um banco de dados é criado / restaurado para o SQL Server 2000 ou superior, cada coluna herda o agrupamento do banco de dados (que é SQL_Latin1_General_CP1_CI_AS , já que era o padrão do SQL Server 7).

Teoricamente, isso não importaria muito, pois se nosso banco de dados é criado do zero em um servidor do cliente, ele herda o agrupamento do servidor do cliente (que normalmente é o padrão de instalação moderno, Latin1_General_CP1_CI_AS ) e tudo funciona. No entanto, esse cenário se quebra quando nos enviam um backup de banco de dados ou enviamos um backup de banco de dados, e recebemos o erro de incompatibilidade de agrupamento temido sempre que o código tenta acessar tabelas temporárias etc.

Nós tentamos instruir os clientes a instalar ou reconstruir suas instâncias do SQL Server para usar nosso agrupamento preferido, mas é claro que isso nem sempre acontece e nem sempre é possível.

Soluções que envolvem a criação de um novo banco de dados e a cópia dos dados não são realmente práticas para nós, precisamos de uma "varinha mágica" que possamos acionar em um banco de dados ativo para corrigir todas as colunas in-loco sem atrapalhar os dados. Estou pensando em escrever um utilitário para fazer isso, mas como será um grande trabalho, alguém tem alguma sugestão mais simples?

    
por Christian Hayter 29.07.2009 / 16:09

3 respostas

6

Uma opção é "testar" seu código em relação à incompatibilidade de agrupamento.

Você pode usar o agrupamento especial "DATABASE_DEFAULT" para coagir sem saber qual é o agrupamento real. Você o utiliza em colunas do tipo char em tabelas temporárias, variáveis de tabela e tabelas de sistema que você precisa usar.

Exemplo:

CREATE TABLE #Currency (CCY CHAR(3))
GO
INSERT #Currency VALUES ('GBP')
INSERT #Currency VALUES ('CHF')
INSERT #Currency VALUES ('EUR')
GO
SELECT Something
FROM myTable M JOIN #Currency C ON M.CCY = C.CCY --error!
GO
-- in join too
SELECT Something
FROM myTable M JOIN #Currency C ON M.CCY = C.CCY COLLATE DATABASE_DEFAULT --no error
GO
DROP TABLE #Currency
GO


CREATE TABLE  #Currency (CCY CHAR(3) COLLATE DATABASE_DEFAULT)
GO
INSERT #Currency VALUES ('GBP')
INSERT #Currency VALUES ('CHF')
INSERT #Currency VALUES ('EUR')
GO
SELECT Something
FROM myTable M JOIN #Currency C ON M.CCY = C.CCY --no error!
GO

DROP TABLE #Currency
GO

Isso também significa que, quando seus clientes migram seu banco de dados para uma nova caixa do SQL Server com outro agrupamento diferente, ele também funciona ...

    
por 29.07.2009 / 17:37
2

Resposta curta é que não há um caminho fácil. Eu tive o mesmo problema no passado.

O que eu diria são duas coisas, primeiro quando seu cliente lhe envia um banco de dados com um agrupamento inesperado, instala uma nova instância do SQL com um agrupamento padrão que corresponda ao DB e trabalhe com ele dentro dele.

O segundo é garantir que o aplicativo funcionará com outros agrupamentos e, em seguida, com os padrões (já que eles podem mudar no futuro) e funcionar corretamente, desde que o agrupamento no servidor SQL e no DB corresponda. Então, é bastante fácil fazer com que o cliente instale o SQL Server com um agrupamento que corresponda ao DB e funcione.

Ou escreva um utilitário que atualizará todas as tabelas, etc em seu banco de dados, como você disse, mas isso pode ser mais trabalho do que você deseja.

    
por 29.07.2009 / 17:08
2

Se todas as colunas no banco de dados forem do mesmo agrupamento, isso só causará problemas ao fazer consultas entre bancos de dados (ou seu aplicativo é sensível à ordem de classificação).

O ponto fixo vem quando você percebe que unir-se a tabelas temporárias é um banco de dados cruzado, já que elas estão em tempdb. Isso é fácil de classificar - apenas certifique-se de que quaisquer colunas de texto em tabelas temporárias sejam explicitamente criadas com a diretiva COLLATE database_default . Isso significa que a coluna será criada com o agrupamento padrão do banco de dados atual em vez da coleta padrão do tempdb (que será o mesmo que o padrão do servidor).

    
por 29.07.2009 / 17:38