Qual o impacto do meu script?

Às vezes pode não parecer, mas tudo dentro de um banco de dados está interligado. Quando pensamos em interligações, é comum lembrar de duas tabelas associadas por uma chave estrangeira ou Foreign Key. No entanto, esta é apenas uma das possíveis relações de dependência dentro do SQL Server. Assim como no caso de uma FK, os objetos envolvidos numa relação de dependência podem ser afetados caso ocorra alguma alteração, seja nos objetos que dependem deles, seja nos objetos dos quais eles dependem. Vejamos um exemplo:

CREATE DATABASE DB1;
GO

USE DB1;
-- Cria uma tabela Tab1
CREATE TABLE dbo.Tab1 (id INT IDENTITY,col1 INT DEFAULT 99);
INSERT INTO dbo.Tab1 DEFAULT VALUES;
GO
-- Cria uma função func1 que depende de Tab1
CREATE FUNCTION dbo.func1 (@id INT)
RETURNS INT AS
BEGIN
DECLARE @col INT;
SELECT @col = col1 FROM dbo.Tab1 WHERE id = @id;
RETURN(@col);
END
GO
-- Cria a procedure sp1 que depende de func1
CREATE PROCEDURE dbo.sp1 (@id INT)
AS
BEGIN
SELECT dbo.func1(@id) + 1;
END
GO

Em nosso DB1, temos uma relação de dependência dos objetos. Então, caso ocorra uma alteração na tabela “dbo.Tab1” onde o nome da coluna “col1” seja alterado para “col2”, a função escalar “dbo.func1” deixará de funcionar e, por sua vez, a procedure “dbo.sp1” também deixará de funcionar. No entanto, a alteração poderia ser na função. Supondo que a função mude sua quantidade de parâmetros, nada será afetado na tabela “Tab1”, mas a procedure não funcionará mais.

Para uma base simples como esta, fica fácil observar esta relação entre os objetos. Já numa base com milhares de objetos, onde alguns deles se relacionam com objetos de outras bases (dependência cross database), esta não é uma tarefa trivial. Vejamos algumas formas de tornar esta verificação mais prática.

Método 1 – Object Explorer

A forma mais prática para verificar a relação de dependência entre os objetos é através do Object Explorer do SSMS. Basta abrir as pastas até o objeto que você quer avaliar, clicar com o botão direito e depois ir em “View Dependencies”.

img01

Assim, será aberta uma janela com duas opções. A primeira, selecionada por padrão, mostra os objetos que dependem de “Tab1”. Expandi o nó em “func1” para mostrar que “sp1” também depende de “Tab1” através da função. Na outra opção, “Objects on which [Tab1] depends”, são listados os objetos dos quais a “Tab1” depende e, neste caso, sabemos que esta tabela não depende de nenhum outro objeto.

img02

O principal ponto positivo deste método é a identificação de toda a relação de dependência. No entanto, além da permissão de SELECT na DMV “sys.sql_expression_dependencies [1]”, é necessária a permissão VIEW DEFINITION [2] em todos os bancos de dados que são referenciados por estes objetos e isso nem sempre é possível. Isso nos leva ao método 2.

Método 2 – T-SQL

Este método é documentado no Books Online [1] e traz dois scripts que servem como as duas opções do método anterior. Então, para retornar os objetos que dependem de “func1”, basta executar:

USE DB1;
GO
SELECT
OBJECT_SCHEMA_NAME ( referencing_id ) AS referencing_schema_name,
OBJECT_NAME(referencing_id) AS referencing_entity_name,
o.type_desc AS referencing_desciption,
COALESCE(COL_NAME(referencing_id, referencing_minor_id), '(n/a)') AS referencing_minor_id,
referencing_class_desc, referenced_class_desc,
referenced_server_name, referenced_database_name, referenced_schema_name,
referenced_entity_name,
COALESCE(COL_NAME(referenced_id, referenced_minor_id), '(n/a)') AS referenced_column_name,
is_caller_dependent, is_ambiguous
FROM sys.sql_expression_dependencies AS sed
INNER JOIN sys.objects AS o ON sed.referencing_id = o.object_id
WHERE referenced_id = OBJECT_ID(N'dbo.func1');
GO

Como resultado, temos o seguinte:

img03

O layout do resultado foi ajustado para caber na página e mostrar as informações interessantes. Na imagem acima, vemos que a procedure “sp1” faz referência à função. Para verificar quais objetos são referenciados por “func1”, ou seja, os objetos dos quais a função depende, executamos o seguinte script:

USE DB1;
GO
SELECT
OBJECT_NAME(referencing_id) AS referencing_entity_name,
o.type_desc AS referencing_desciption,
COALESCE(COL_NAME(referencing_id, referencing_minor_id), '(n/a)') AS referencing_minor_id,
referencing_class_desc,
referenced_server_name, referenced_database_name, referenced_schema_name,
referenced_entity_name,
COALESCE(COL_NAME(referenced_id, referenced_minor_id), '(n/a)') AS referenced_column_name,
is_caller_dependent, is_ambiguous
FROM sys.sql_expression_dependencies AS sed
INNER JOIN sys.objects AS o ON sed.referencing_id = o.object_id
WHERE referencing_id = OBJECT_ID(N'dbo.func1');
GO

Como esperado, o resultado é o seguinte:

img04

Assim vemos que “func1” depende de (ou faz referência à) “Tab1”. Vale lembrar que este método não irá listar toda a relação de dependência, mas apenas a relação direta de referências. Desta forma podemos verificar e saber qual será o impacto da mudança que teremos de fazer.

Próximos Passos

Agora que já sabemos quais objetos serão afetados com as alterações que faremos, precisamos tomar algumas providências como:

  • Entrar em contato com os responsáveis pelos objetos afetados conversando sobre as mudanças necessárias e os possíveis impactos;
  • Documentar as alterações necessárias juntamente com o objeto registrando quais foram as alterações, onde ocorreram, quando ocorreram e quem foi o autor da alteração;
  • Após a alteração do objeto no ambiente de desenvolvimento, realizar testes rigorosos tanto do objeto alterado como dos objetos afetados.

Desta forma, realizamos manutenções de código e alterações de objetos de uma maneira mais consciente e controlada. Lembre-se, o próximo código a quebrar pode ser o seu.

Links:

[1] sys.sql_expression_dependencies

[2] VIEW DEFINITION

 

Anúncios

2 pensamentos sobre “Qual o impacto do meu script?

  1. Bacana o post.
    Nessas horas me pergunto porque Schemabinding não é um parâmetro mais abrangente.
    Destaque pra frase: “Lembre-se, o próximo código a quebrar pode ser o seu.” – 10/10
    Abs

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s