使用:SQL SERVER 2016/2017
我当前正在使用sys.dm_exec_describe_first_result_set_for_object
来检索大量过程的输出定义。查询树导航过程时,看到一些意外结果。我已经将问题追溯到内置过程如何识别迭代cte中的空对象的问题。
要复制问题的代码:
DROP TABLE IF EXISTS dbo.TestTable1;
DROP PROC IF EXISTS dbo.TestTableProc1;
DROP PROC IF EXISTS dbo.TestTableProc2;
CREATE TABLE dbo.TestTable1 (ParentID INT NOT NULL
, ChildID INT NOT NULL
, Guid UNIQUEIDENTIFIER NOT NULL);
GO
CREATE PROC dbo.TestTableProc1 (@Value1 INT)
AS
BEGIN;
WITH cte AS
(SELECT T1.ParentID
, T1.ChildID
, T1.Guid
FROM dbo.TestTable1 T1
WHERE T1.ParentID = @Value1
UNION ALL
SELECT T1.ParentID
, T1.ChildID
, T1.Guid
FROM dbo.TestTable1 T1)
SELECT cte.ParentID
, cte.ChildID
, cte.Guid
FROM cte;
END;
GO
CREATE PROC dbo.TestTableProc2 (@Value1 INT)
AS
BEGIN;
WITH cte AS
(SELECT T1.ParentID
, T1.ChildID
, T1.Guid
FROM dbo.TestTable1 T1
WHERE T1.ParentID = @Value1
UNION ALL
SELECT cte.ParentID
, cte.ChildID
, cte.Guid
FROM dbo.TestTable1 T1
JOIN cte ON T1.ParentID = cte.ChildID)
SELECT cte.ParentID
, cte.ChildID
, cte.Guid
FROM cte;
END;
GO
SELECT 'dbo.TestTableProc1'
, name
, is_nullable
FROM sys.dm_exec_describe_first_result_set_for_object(OBJECT_ID('dbo.TestTableProc1'), 0)
UNION ALL
SELECT 'dbo.TestTableProc2'
, name
, is_nullable
FROM sys.dm_exec_describe_first_result_set_for_object(OBJECT_ID('dbo.TestTableProc2'), 0);
DROP PROC IF EXISTS dbo.TestTableProc1;
DROP PROC IF EXISTS dbo.TestTableProc2;
DROP TABLE IF EXISTS dbo.TestTable1;
这给出了结果集:
从结果中可以看到,TestTableProc1
正确地将所有字段标识为非null。其中TestTableProc2
将所有字段标识为可为空,而永远不会为空。
作为解决方案,我可以将整个过程移到一个子过程中,然后使用当前名称调用该子过程并添加一个WITH RESULTSET
子句以锁定输出。虽然这是一个可行的解决方法,但它意味着要降低性能,并在不需要的地方向数据库添加其他过程。
我需要一种获取正确结果集描述的方法,因为这是一个罕见的调用,我可以在这里提高性能,而不必更改主过程本身。
非常感谢您收到任何选项。