Existe uma maneira mais fácil de resolver incompatibilidades de agrupamento 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 antes, 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 caracteres. Em vez disso, quando um banco de dados é criado / restaurado para o SQL Server 2000 ou superior, todas as colunas herdam o agrupamento do banco de dados (o que acontece SQL_Latin1_General_CP1_CI_ASdesde que esse era o padrão do SQL Server 7).

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

Tentamos educar os clientes para 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.

As 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 acenar em um banco de dados ativo para corrigir todas as colunas no local sem perturbar 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?

Christian Hayter
fonte

Respostas:

6

Uma opção é "revisar" seu código contra incompatibilidade de agrupamento.

Você pode usar o agrupamento especial "DATABASE_DEFAULT" para coagir sem saber qual é o agrupamento real. Você o usa 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 ...

gbn
fonte
2

Resposta curta: não existe uma maneira fácil. Eu tive o mesmo problema no passado.

O que eu diria é duas coisas: primeiro, quando seu cliente envia um banco de dados com um agrupamento inesperado, instale uma nova instância SQL com um agrupamento padrão que corresponda ao banco de dados e trabalhe nele.

A segunda é garantir que o aplicativo funcione com outros agrupamentos e não com os padrões (já que esses podem mudar no futuro) e funcionará corretamente, desde que o agrupamento no servidor SQL e no DB correspondam. Então, é bastante fácil que o cliente instale o SQL Server com um agrupamento que corresponda ao banco de dados e funcione.

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

SpaceManSpiff
fonte
2

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

O ponto difícil é quando você percebe que a associação a tabelas temporárias é entre bancos de dados, como estão no tempdb. Isso é fácil de classificar - apenas certifique-se de que quaisquer colunas de texto em tabelas temporárias sejam explicitamente criadas com a COLLATE database_defaultdiretiva. Isso significa que a coluna será criada com o agrupamento padrão do banco de dados atual em vez da coleção padrão do tempdb (que será igual ao padrão do servidor).

David Spillett
fonte