【问题标题】:T-SQL Puzzler - Crawling Object DependenciesT-SQL Puzzler - 爬取对象依赖项
【发布时间】:2010-09-27 15:16:58
【问题描述】:

此代码涉及递归存储过程调用和避免游标名称冲突的“不太好”的方法。最后我不在乎它是否使用游标。只是寻找最优雅的方法。我主要将其用作追踪存储过程层次结构的简单方法(无需购买产品)。我在“动态 sql”中尝试了游标,但运气不佳。我想深入大约 10 级。

想要的输出:

sp_Master_Proc_Name -- sp_Child_Proc_1_Name ---- sp_Sub_Proc_1_Name -- sp_Child_Proc_2_Name -- sp_Child_Proc_3_Name

它不漂亮,但这里是代码(它没有按预期工作)

    CREATE PROCEDURE SP_GET_DEPENDENCIES
    (
      @obj_name varchar(300),
      @level int
    )
    AS
    DECLARE @sub_obj_name varchar(300)
    IF @level = 1
      BEGIN
        PRINT @obj_name
      END

    IF @level = 1
      BEGIN 
        DECLARE the_cursor_1 CURSOR FOR 
            SELECT DISTINCT REPLICATE('--', @level) + ' ' + c.name FROM dbo.sysdepends a
              INNER JOIN dbo.sysobjects b ON a.id = b.id
              INNER JOIN dbo.sysobjects c ON a.depid = c.id
              WHERE b.name = @obj_name
        OPEN the_cursor_1
        SET @level = @level + 1
        FETCH NEXT FROM the_cursor_1 INTO @sub_obj_name 
        WHILE @@FETCH_STATUS = 0 
          BEGIN 
            PRINT @sub_obj_name
            EXEC SP_GET_DEPENDENCIES @sub_obj_name, @level 
            FETCH NEXT FROM the_cursor_1 INTO @sub_obj_name 
          END
        CLOSE the_cursor_1
        DEALLOCATE the_cursor_1
      END

    IF @level = 2
      BEGIN 
        DECLARE the_cursor_2 CURSOR FOR 
            SELECT DISTINCT REPLICATE('--', @level) + ' ' + c.name FROM dbo.sysdepends a
              INNER JOIN dbo.sysobjects b ON a.id = b.id
              INNER JOIN dbo.sysobjects c ON a.depid = c.id
              WHERE b.name = @obj_name
        OPEN the_cursor_2
        SET @level = @level + 1
        FETCH NEXT FROM the_cursor_2 INTO @sub_obj_name 
        WHILE @@FETCH_STATUS = 0 
          BEGIN 
            PRINT @sub_obj_name
            EXEC SP_GET_DEPENDENCIES @sub_obj_name, @level 
            FETCH NEXT FROM the_cursor_2 INTO @sub_obj_name 
          END
        CLOSE the_cursor_2
        DEALLOCATE the_cursor_2
      END

    IF @level = 3
      BEGIN 
        DECLARE the_cursor_3 CURSOR FOR 
            SELECT DISTINCT REPLICATE('--', @level) + ' ' + c.name FROM dbo.sysdepends a
              INNER JOIN dbo.sysobjects b ON a.id = b.id
              INNER JOIN dbo.sysobjects c ON a.depid = c.id
              WHERE b.name = @obj_name
        OPEN the_cursor_3
        SET @level = @level + 1
        FETCH NEXT FROM the_cursor_3 INTO @sub_obj_name 
        WHILE @@FETCH_STATUS = 0 
          BEGIN 
            PRINT @sub_obj_name
            EXEC SP_GET_DEPENDENCIES @sub_obj_name, @level 
            FETCH NEXT FROM the_cursor_3 INTO @sub_obj_name 
          END
        CLOSE the_cursor_3
        DEALLOCATE the_cursor_3
      END

【问题讨论】:

  • 您使用的是 SQL 2005 吗?如果是这样,您可能可以使用 CTE 在单个选择语句中执行此操作。如果没有,您可能仍然可以使用临时表在单个非递归 SP 中执行此操作。只要继续抓住剩下孩子的任何行。如果我明天感冒好了,我会试着写点东西。
  • 酷,我希望将其视为 CTE。是不是只有我一个人……但 CTE 让我的大脑比平时更痛。
  • 只是另一个想法。在 Stackoverflow 上协作处理代码片段真是太酷了!我希望这个网站是大约 10 年前我刚开始创业的时候。
  • 嘿...看起来 NCX 的链接实际上包含了我正在考虑的两个答案

标签: sql sql-server tsql recursion


【解决方案1】:

请参阅this Stackoverflow question,了解按深度对查询表外键依赖项进行排序的讨论——这与您正在讨论的问题类似。答案中至少有两个针对该问题的可行解决方案,与您正在做的事情的唯一真正区别是他们正在爬行的表格。 This posting 有一个 DB 逆向工程脚本,展示了如何使用许多主要的数据字典表。

【讨论】:

  • 谢谢,这将帮助我解决我正在处理的一些 T-SQL 问题。
【解决方案2】:

对于 ms sql server,你可以使用 CURSOR LOCAL,那么游标对于 sproc 调用是本地的,你的代码就变得更简单了:

CREATE PROCEDURE uspPrintDependencies
(
    @obj_name varchar(300),
    @level int
)
AS
SET NOCOUNT ON
DECLARE @sub_obj_name varchar(300)

if @level > 0 begin
    PRINT Replicate(' ',@level) + @obj_name
end
else begin
    PRINT @obj_name
end

DECLARE myCursor CURSOR LOCAL FOR 
    SELECT 
        DISTINCT c.name 
    FROM dbo.sysdepends a
        INNER JOIN dbo.sysobjects b ON a.id = b.id
        INNER JOIN dbo.sysobjects c ON a.depid = c.id
    WHERE b.name = @obj_name
OPEN myCursor
SET @level = @level + 1
FETCH NEXT FROM myCursor INTO @sub_obj_name 
WHILE @@FETCH_STATUS = 0 BEGIN 
    EXEC uspPrintDependencies @sub_obj_name, @level 
    FETCH NEXT FROM myCursor INTO @sub_obj_name 
END
CLOSE myCursor
DEALLOCATE myCursor
GO

【讨论】:

  • 甜蜜!这是我在光标碰撞之前所拥有的(嗯,减去 local 关键字)。不知道有一个本地关键字。明天我会将它合并到我的代码中并尝试一下。
  • @[Bruno Tyndall]:还有另一个关键字 forward_only 或 fast_foward 或类似的东西,您可能也应该将其用作优化
猜你喜欢
  • 1970-01-01
  • 2016-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-12
  • 2010-09-22
  • 2013-03-03
  • 2019-01-24
相关资源
最近更新 更多