此代码涉及一个递归的存储过程调用和一个避免游标名称冲突的“不那么好”的方法。最后我不在乎它是否使用游标。只是寻找最优雅的方法。我主要将它用作跟踪存储过程层次结构(不购买产品)的简单方法。我在“动态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
答案 0 :(得分:6)
对于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
答案 1 :(得分:3)
有关按深度排序查询表外键依赖关系的讨论,请参阅this Stackoverflow question - 这与您正在讨论的问题类似。答案中至少有两个解决这个问题的工作方案,而你所做的唯一真正的不同就是他们正在抓取的表格。 This posting有一个DB逆向工程脚本,它显示了如何使用许多主数据字典表。