Estou lidando com uma situação no SQL Server 2008 em que cada cliente é configurado como seu próprio banco de dados, com cada banco de dados tendo estruturas de tabelas idênticas.
Eu tenho uma consulta que seleciona cerca de 20 tabelas diferentes em um banco de dados e insere os registros em um banco de dados de relatórios. O que gostaríamos de fazer é repetir esse processo para cada banco de dados, de modo que todas as informações de relatórios em todos os bancos de dados de clientes estejam contidas em um banco de dados de relatórios consolidado.
A maneira "fácil" seria apenas copiar/colar o código e localizar/substituir todos os nomes do banco de dados para que o script seja executado em todos os clientes. Existe alguma maneira melhor do que isso?
Esta resposta pressupõe que você tenha um banco de dados/tabela mestre de clientes e seus nomes de banco de dados associados, ou alguma maneira de descobrir quais bancos de dados em uma determinada instância do SQL Server têm bancos de dados relevantes que você deseja consultar.
Como isso é para fins de relatório, convém implementar alguma forma de técnica de instantâneo para garantir que os conjuntos de dados sejam consolidados no mesmo ponto no tempo, pelo menos por cliente. Como um bom efeito colateral, essas técnicas geralmente também aliviam os efeitos de bloqueio/bloqueio da execução desses tipos de consultas diretamente nos dados de produção.
SQL dinâmico puro
Usando a lista principal, crie uma instrução SQL que use nomes de 3 partes como você está fazendo agora, mas, em vez disso, injete o nome do banco de dados dinamicamente. Não está claro na pergunta em que formato os dados vão acabar, mas parece que você quer
UNION ALL
tudo junto, o que é facilmente realizado.Isso pode ser vantajoso para você agora porque exigirá muito pouco trabalho inicial.
A desvantagem é que essa abordagem não é muito flexível e rapidamente se torna complicada se você precisar executar a consulta quando as revisões individuais do banco de dados forem diferentes (ou seja, a consulta foi vinculada a uma determinada revisão do banco de dados e, quando uma atualização do banco de dados foi implantada, não teve sucesso para todos os clientes). Também pode haver problemas ou complicações dependendo do modelo de segurança que você está usando para esses bancos de dados.
Objeto(s) Baseado(s) em Banco de Dados + SQL Dinâmico
Esta solução cria objetos permanentes dentro de cada banco de dados que você pode consultar em um processo externo. Normalmente, isso significa uma exibição, um procedimento armazenado ou uma função com valor de tabela. O SQL dinâmico será usado para injetar os nomes do banco de dados na consulta como acima, mas desta vez tudo o que é necessário é selecionar ou executar o objeto do banco de dados em vez da consulta bruta diretamente.
Este método oferece todas as vantagens de proteger seu código por trás de uma interface da mesma forma que faria usando exibições, procedimentos armazenados, etc., no código do aplicativo. Isso também resolve os problemas de segurança com muito mais facilidade.
A desvantagem, é claro, é que isso requer um pouco mais de trabalho e gerenciamento inicial e que o(s) objeto(s) consultado(s) só pode(m) ser implantado(s) em atualizações de banco de dados, em vez de independentemente.
Minha opinião pessoal é que a última abordagem é uma solução de longo prazo muito melhor, portanto, nesse tipo de cenário, é por essa que eu optaria. Para tipos ad hoc de consultas, usar a abordagem SQL dinâmica pura é bom.
Sei que já existe uma resposta aceita, mas para referência futura, uma alternativa é:
Se o seu script não fizer referência ao nome do banco de dados do cliente (ou seja, é apenas qualificado pelo esquema), o script em lote a seguir permitirá (via sqlcmd) executá-lo em uma lista de bancos de dados no host local sem modificar o script.
Ele solicitará o nome/caminho do arquivo do script SQL a ser executado e o nome/caminho de um arquivo de texto contendo uma lista de bancos de dados a serem executados (por exemplo, um txt simples com um nome de banco de dados em cada linha).
Ele registrará a saída retornada pelo SQL Server em um arquivo de log no diretório local.
Notas Adicionais: