【问题标题】:How can I detect broken stored procedures after a schema change?架构更改后如何检测损坏的存储过程?
【发布时间】:2020-11-13 15:01:38
【问题描述】:

我有一个包含数百个表和数百个存储过程的数据库。 数据库架构已更改(例如:某些表/列已重命名,某些列已被删除/添加等)。

问题是:如何检测受这些更改影响的程序(执行时会产生错误),无需实际执行它们,因为一个一个地执行它们需要大量的手动操作和耗时的工作?

编辑

到目前为止,我找到的最接近的解决方案是: sys.dm_sql_referenced_entities。像SELECT * FROM sys.dm_sql_referenced_entities ('dbo.procedure_name', 'OBJECT'); 这样的查询 如果过程 procedure_name 被那些破坏,则返回错误 变化。

所以,我可以获取所有程序的名称并运行上 在循环中查询每个过程名称,并在其中执行某种逻辑 在那里,就像在 错误的情况。


【问题讨论】:

    标签: sql-server database-administration


    【解决方案1】:

    您可以尝试此查询,请注意,在某些情况下,这也可能列出误报。

    查询以获取invalid 对象的列表:

    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
    

    更多信息可以找到here

    当您重新设计方案时,其他有用的查询可能是这样的

    查询以查找从其他人调用的过程:

    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 )
    

    查询以查找正在使用另一个对象的所有对象:

    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%'
    

    【讨论】:

    • 看起来相当成熟和有前途。到目前为止,它已经为我发现了很多损坏的程序。现在我只需要检查是否有您所说的误报。
    • @Ergis 好吧,我希望它能为您节省一些时间。很高兴能帮上忙
    • @Ergis 误报可能是当程序在某些极少数情况下需要来自另一个数据库的数据时,或者在使用自定义类型时。如果您不使用它,您将不会有误报
    猜你喜欢
    • 2011-04-01
    • 1970-01-01
    • 2012-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多