【问题标题】:Stored procedures reverse engineering存储过程逆向工程
【发布时间】:2010-09-09 08:30:15
【问题描述】:

我们在处理大量遗留存储过程时遇到了问题。你们是否推荐任何可以帮助更好地理解这些程序的工具?某种识别过程间依赖关系和/或过程与表依赖关系的逆向工程。可以是免费或商业工具。

谢谢!

【问题讨论】:

    标签: database stored-procedures reverse-engineering legacy


    【解决方案1】:

    比“依赖跟踪器”更便宜的解决方案是数据字典表 sys.sql_dependencies,可以从数据字典中查询此数据。 Oracle 有一个具有类似功能的数据字典视图,称为 DBA_DEPENDENCIES(加上等效的 USER_ 和 ALL_ 视图)。使用其他数据字典表(sys.tables/DBA_TABLES)等可以生成对象依赖报告。

    如果您感觉特别热衷,可以使用递归查询(Oracle CONNECT BY 或 SQL Server 公用表表达式)来构建完整的对象依赖关系图。

    以下是 sys.sql_dependencies 上的递归 CTE 示例。它将为每个依赖项及其深度返回一个条目。对于每个依赖关系,项目可以多次出现,可能在不同的深度。我没有可用的 Oracle 实例来构建对 DBA_DEPENDENCIES 的 CONNECT BY 查询,因此欢迎任何拥有编辑权限、时间和专业知识的人注释或编辑此答案。

    还要注意sys.sql_dependencies,您可以从referenced_minor_id 获取列引用。这可用于(例如)确定哪些列在暂存区域的 ETL 存储过程中实际使用,其中来自源的 DB 表副本具有比实际使用的列更多的列。

    with dep_cte as (
    select o2.object_id  as parent_id
          ,o2.name       as parent_name
          ,o1.object_id  as child_id
          ,o1.name       as child_name
          ,d.referenced_minor_id
          ,1 as hierarchy_level
      from sys.sql_dependencies d
      join sys.objects o1
        on o1.object_id = d.referenced_major_id
      join sys.objects o2
        on o2.object_id = d.object_id
     where d.referenced_minor_id in (0,1)
       and not exists
           (select 1
              from sys.sql_dependencies d2
             where d2.referenced_major_id = d.object_id)
    
    union all
    
    select o2.object_id  as parent_id
          ,o2.name       as parent_name
          ,o1.object_id  as child_id
          ,o1.name       as child_name
          ,d.referenced_minor_id
          ,d2.hierarchy_level + 1 as hierarchy_level
      from sys.sql_dependencies d
      join sys.objects o1
        on o1.object_id = d.referenced_major_id
      join sys.objects o2
        on o2.object_id = d.object_id
      join dep_cte d2
        on d.object_id = d2.child_id
     where d.referenced_minor_id in (0,1)
    )
    
    select *
      from dep_cte
     order by hierarchy_level
    

    我现在要向社区开放。可以方便地访问正在运行的 Oracle 实例的人在这里发布 CONNECT BY 递归查询吗?请注意,这是特定于 SQL 服务器的,问题所有者已经明确表示他正在使用 Oracle。我没有可运行的 Oracle 实例来开发和测试任何东西。

    【讨论】:

    • 不知道。但我认为它不是很人性化。不过我会看看的。
    【解决方案2】:

    Redgate 有一个名为SQL Dependency Tracker 的相当昂贵的产品,似乎可以满足要求。

    【讨论】:

      【解决方案3】:

      我认为Red Gate Dependency Tracker mentioned by rpetrich 是一个不错的解决方案,它运行良好,而且 Red Gate 有 30 天的试用期(理想情况下,足够您进行取证)。

      我还会考虑隔离系统并运行 SQL Profiler,它会向您显示表上的所有 SQL 操作。这通常是构建序列图或您选择记录这些代码的良好起点。祝你好运!

      【讨论】:

        【解决方案4】:

        Redgate SQL 文档。生成的文档包括交叉引用的依赖信息。例如,对于每个表,它列出了引用该表的视图、存储过程、触发器等。

        【讨论】:

          【解决方案5】:

          存储过程在哪个数据库中? Oracle、SQL Server 还是其他?

          根据评论进行编辑:鉴于您当时使用的是 Oracle,请查看 TOAD。我在其中使用了一个称为代码路线图的功能,它允许您以图形方式显示数据库中的 PL/SQL 相互依赖关系。它可以在纯代码模式下运行,显示运行时调用堆栈依赖关系,或者在代码加数据模式下,它还向您显示您的代码所触及的数据库对象(表、视图、触发器)。

          (注意 - 我是 TOAD 用户,推荐它没有任何好处)

          【讨论】:

            【解决方案6】:

            这不是真正深入或彻底,但我认为如果您使用的是 MS SQL Server 或 Oracle(也许 Nigel 可以帮助提供 PL-SQL 示例)...Nigel 正在做一些事情。这只会深入 3 个依赖项,但可以修改为你需要的任何深度。这不是最漂亮的东西……但它很实用……

            select 
                so.name + case when so.xtype='P' then ' (Stored Proc)' when so.xtype='U' then ' (Table)' when so.xtype='V' then ' (View)' else ' (Unknown)' end as EntityName, 
                so2.name + case when so2.xtype='P' then ' (Stored Proc)' when so2.xtype='U' then ' (Table)' when so2.xtype='V' then ' (View)' else ' (Unknown)' end as FirstDependancy,
                so3.name + case when so3.xtype='P' then ' (Stored Proc)' when so3.xtype='U' then ' (Table)' when so3.xtype='V' then ' (View)' else ' (Unknown)' end as SecondDependancy,
                so4.name + case when so4.xtype='P' then ' (Stored Proc)' when so4.xtype='U' then ' (Table)' when so4.xtype='V' then ' (View)' else ' (Unknown)' end as ThirdDependancy
            from 
              sysdepends sd 
                inner join sysobjects as so on sd.id=so.id 
                left join sysobjects as so2 on sd.depid=so2.id
                left join sysdepends as sd2 on so2.id=sd2.id and so2.xtype not in ('S','PK','D')
                left join sysobjects as so3 on sd2.depid=so3.id and so3.xtype not in ('S','PK','D')
                left join sysdepends as sd3 on so3.id=sd3.id and so3.xtype not in ('S','PK','D')
                left join sysobjects as so4 on sd3.depid=so4.id and so4.xtype not in ('S','PK','D')
            where so.xtype = 'P' and left(so.name,2)<>'dt'
            group by so.name, so2.name, so3.name, so4.name, so.xtype, so2.xtype, so3.xtype, so4.xtype
            

            【讨论】:

              【解决方案7】:

              How to find the dependency chain of a database object (MS SQL Server 2000(?)+) 雅各布·塞巴斯蒂安(Jacob Sebastian)

              每次他需要部署新报表或修改现有报表时 报告,他需要知道依赖的数据库对象是什么 给定的报告存储过程。有时报告非常 复杂,每个存储过程可能有几十个依赖 对象和每个依赖对象可能依赖于其他几十个 对象。

              他需要一种方法来递归地找到一个对象的所有依赖对象 给定的存储过程。我用CTE写了一个递归查询来实现 这个。

              【讨论】:

                【解决方案8】:

                逆向工程的最佳工具是 APEX。太奇妙了。它甚至可以追踪到 .NET 程序集并告诉您在哪里使用了 proc。它是迄今为止同类产品中最深的产品。 RedGate 有很好的其他工具,但在这种情况下没有。

                【讨论】:

                  猜你喜欢
                  • 2017-06-29
                  • 2014-12-20
                  • 1970-01-01
                  • 2012-08-26
                  • 2010-10-15
                  • 2012-05-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-09-15
                  相关资源
                  最近更新 更多