Como posso detectar procedimentos armazenados quebrados após uma alteração no esquema?

11

Modifiquei uma tabela central no meu banco de dados e sp_depends literalmente retorna centenas de resultados, e estou preocupado que alguns desses procedimentos armazenados possam não ser mais compilados após minha alteração.

É fácil verificar um único procedimento armazenado (basta executar novamente o script de alteração e verificar se a operação foi bem-sucedida), mas fazer isso em mais de 100 procedimentos é um pouco complicado.

Eu sei que posso usar um script como este para recompilar todos os objetos do meu banco de dados, mas a operação real ocorrerá na próxima vez que o procedimento armazenado for executado, não imediatamente, para que isso não pareça apropriado no meu caso.

Eu também estava pensando que poderia descartar todos os procedimentos armazenados e ressignificar meu banco de dados com meu sistema de controle de origem, mas essa opção, embora viável, não é muito elegante. Existe um jeito melhor de fazer isso?

Estou usando o SQLServer 2008 R2 e meus scripts de banco de dados são armazenados em um projeto de banco de dados do VS 2008.


Para esclarecer, não estou defendendo que se deva confiar apenas nessa abordagem para testar o código. Assim como no c #, você detecta instantaneamente erros de sintaxe em outros arquivos dependentes à medida que codifica (e depois usa outras estratégias para testar, como testes de unidade, que geralmente são várias ordens de magnitude mais lentas), acho que faria sentido detectar dependências SQL erros em segundos, em vez de ter que executar um teste funcional completo, que normalmente pode levar algumas horas para ser concluído.

Brann
fonte

Respostas:

7

Que tal você executar seus testes de unidade, funcional, integração e desempenho? Se você não tiver nenhum teste, é um momento sério para começar a considerar o esquema do banco de dados como código e tratá-lo como tal, incluindo controle e teste de versão. Alex Kuznetsov tem um livro inteiro dedicado a esse assunto: Programação Defensiva de Banco de Dados com o SQL Server .

Remus Rusanu
fonte
Os testes nem sempre cobrem 100% do código e, quando o fazem, normalmente levam algumas horas para serem executados. Em c #, posso detectar se meu código ainda é compilado em segundos (independentemente de sua correção). Isso não significa que eu deva enviar o código (independentemente do código ser c # ou PLSQL) para a produção sem testá-lo adequadamente, mas não parece irracional ter uma maneira de detectar rapidamente dependências quebradas, não é?
Brann
2
Infelizmente, o estado da arte do SQL Server agora no que diz respeito à detecção de dependência no procedimento armazenado está 'profundamente quebrado', consulte Noções básicas sobre dependências do SQL ou Como manter os sistemas dependentes do SQL Server 2008 . Há ainda ferramentas de terceiros que tentam abordar a questão
Remus Rusanu
2
Isso torna os testes unitários / funcionais praticamente a única maneira confiável de detectar alterações significativas.
Remus Rusanu
11
Para uma verificação rápida, o Visual Studio Database Projects faz um trabalho bastante decente na validação de qualquer alteração.
Remus Rusanu
4

É uma solução alternativa, mas você pode gerar os scripts CREATE PROCEDURE para o banco de dados (clique com o botão direito do mouse em banco de dados -> tarefas -> gerar scripts), localize e substitua CREATE PROCEDURE por ALTER PROCEDURE e, em seguida, analise.

Espero que você obtenha uma resposta melhor aqui - também estou interessado! :)

JHFB
fonte
Não estou marcando sua resposta como aceita, porque ainda espero uma solução mais limpa (espero que seja com script), mas você definitivamente recebe meu +1! Obrigado.
Brann
3
Essa abordagem não informa se você está fazendo referência a uma tabela inexistente .
9118 Nick Chammas
Essa abordagem também não funcionará se o script gerado for maior que cerca de 30 mil linhas. Eu odeio que eu sei disso ..
Eonasdan 27/01
3

Você pode usar o SSDT (Sql Server Data Tools). O Microsoft Visual Studio permite criar um projeto do Sql Server. Um então importa o banco de dados para o projeto e, em seguida, cria o projeto. Se houver procedimentos ou objetos armazenados quebrados, você receberá um erro de compilação.

VenVig
fonte
Acrescentarei que você pode gerar facilmente um novo script de criação de banco de dados a partir do projeto SSDT e executar em um ambiente de teste, que será uma verificação bastante completa de que não há procs / triggers / etc interrompidos devido a alterações no esquema.
AaronLS
3

Você pode querer olhar para esta pergunta de SO . Estou procurando uma maneira confiável de verificar os procedimentos armazenados do T-SQL. Alguém tem um? que está perguntando essencialmente a mesma coisa, com várias respostas.

Para criar o script que Alaa Awad postou ... isso deve mostrar o esquema e o banco de dados dos objetos referenciados e referenciados. Se você estiver usando muitas tabelas temporárias por meio de aliases (que às vezes são exibidos ao usar sys.sql_expression_dependencies), parâmetros UDTT ou outros recursos dinâmicos, pode ser necessário usar as funções sys.dm_sql_referenced_entitiesou, em sys.dm_sql_referencing_entitiesvez disso / também.

SELECT
    DB_NAME() + '.' + OBJECT_SCHEMA_NAME(sed.referencing_id) + '.' + OBJECT_NAME(sed.referencing_id) AS [referencingObject],
    isnull(sed.referenced_server_name + '.', '') + isnull(sed.referenced_database_name + '.', DB_NAME() + '.') + isnull(sed.referenced_schema_name + '.', OBJECT_SCHEMA_NAME(sed.referencing_id) + '.') + sed.referenced_entity_name AS [missingReference]
FROM 
    sys.sql_expression_dependencies sed
WHERE 
    sed.is_ambiguous = 0
    AND OBJECT_ID(isnull(sed.referenced_database_name + '.', DB_NAME() + '.') + isnull(sed.referenced_schema_name + '.', OBJECT_SCHEMA_NAME(sed.referencing_id) + '.') + sed.referenced_entity_name) IS NULL
ORDER BY
    [referencingObject], [missingReference]
Arkaine55
fonte
11
Deve-se adicioná-los à cláusula where: / * Não é um tipo de usuário existente / AND sed.referenced_entity_name NOT IN (SELECT [name] FROM sys.types) / Não é um alias * / AND sed.referenced_schema_name NÃO É NULL
JasonBluefire
1

use os sys.sql_expression_dependencies adicionados no sql server 2008

CREATE PROCEDURE [dbo].[spMaintenance_Find_Broken_Dependencies]

AS
SELECT
    OBJECT_NAME(referencing_id) AS [referencingObject],
    referenced_entity_name AS [missingReference]
FROM 
    sys.sql_expression_dependencies
WHERE 
    is_ambiguous = 0
    AND OBJECT_ID(referenced_entity_name) IS NULL
ORDER BY 
    OBJECT_NAME(referencing_id), referenced_entity_name

GO
Alaa Awad
fonte
Isso pode ser útil, no entanto, não é tão simples quanto o esquema também precisa levar em consideração. Também estou recebendo problemas em que o sys.sql_expession_dependencies está exibindo o alias usado em vez da tabela dependente real, que obviamente falha no teste de object_id (). Por fim, ele exibe tabelas definidas pelo usuário passadas como parâmetros para procedimentos armazenados - o que não é realmente útil.
Tabloo Quijico