Ergis
Ergis

Reputation: 1229

How can I detect broken stored procedures after a schema change?

I have a database with up to hundreds of table and hundreds of stored procedures. The database schema has been altered (e.x: some tables/columns have been renamed, some columns have been deleted/added etc).

The question is: how to detect the procedures that have been impacted by those changes (that produce error on execution), without actually executing them, because executing them one by one is a lot of manual and time-consuming work?

Edit

The closest solution I've found until now is this: sys.dm_sql_referenced_entities. A query like SELECT * FROM sys.dm_sql_referenced_entities ('dbo.procedure_name', 'OBJECT'); returns an error if procedure procedure_name is broken by those changes.

So, I can get the names of all procedures and run the upper query in a loop for each procedure name, and do some kind of logic in there, like printing the procedure name in case of error.


Upvotes: 1

Views: 735

Answers (1)

GuidoG
GuidoG

Reputation: 12014

You can try this query, mind you that this can also list false positives in certain cases.

Query to get a list of invalid objects:

select QuoteName(OBJECT_SCHEMA_NAME(referencing_id)) + '.' + QuoteName(OBJECT_NAME(referencing_id)) AS ProblemObject,
       o.type_desc,
       ISNULL(QuoteName(referenced_server_name) + '.', '')
         + ISNULL(QuoteName(referenced_database_name) + '.', '')
         + ISNULL(QuoteName(referenced_schema_name) + '.', '')
         + QuoteName(referenced_entity_name) AS MissingReferencedObject
from   sys.sql_expression_dependencies sed
  left join sys.objects o on sed.referencing_id=o.object_id
where  (is_ambiguous = 0)
and  (OBJECT_ID(ISNULL(QuoteName(referenced_server_name) + '.', '')
       + ISNULL(QuoteName(referenced_database_name) + '.', '')
       + ISNULL(QuoteName(referenced_schema_name) + '.', '')
       + QuoteName(referenced_entity_name)
     ) IS NULL)
order by ProblemObject, MissingReferencedObject

more info can be found here

Other useful queries when you are redesigning your scheme can be this

query to find procedures that are called from others:

declare @t table (procname varchar(200), called_in varchar(200))
declare @ProcName varchar(200)

declare crProcs cursor local FAST_FORWARD READ_ONLY for
         select distinct
                o.name as procedure_name
         from   sys.sql_modules m
           inner join sys.objects o ON m.object_id = o.object_id
         where o.Type = 'P'

open crProcs
fetch next from crProcs into @ProcName
while @@FETCH_STATUS = 0
begin
     insert into @t (procname, called_in)
     select @ProcName,
            o.name
     from   sys.sql_modules m
       inner join sys.objects o ON m.object_id = o.object_id
     where  m.definition Like '%' + @ProcName + '%'
     group by o.name

     fetch next from crProcs into @ProcName
end 
close crProcs
deallocate crProcs

select * 
from   @t t
where  1 < (select count(1) from @t t2 where t2.procname = t.procname )

query to find all objects where another object is being used:

SELECT DISTINCT
       o.name AS Object_Name,
       o.type_desc,
       m.*
FROM   sys.sql_modules m
  INNER JOIN sys.objects o ON m.object_id = o.object_id
WHERE m.definition Like '%MyTableThatIWantToChangeTheScheme%'

Upvotes: 1

Related Questions