Dm_exec_describe_first_result_set_for_object在迭代ctes上返回null

时间:2018-08-28 09:13:47

标签: sql sql-server stored-procedures iteration common-table-expression

使用: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;

这给出了结果集:

enter image description here

从结果中可以看到,TestTableProc1正确地将所有字段标识为非null。其中TestTableProc2将所有字​​段标识为可为空,而永远不会为空。

作为解决方案,我可以将整个过程移到一个子过程中,然后使用当前名称调用该子过程并添加一个WITH RESULTSET子句以锁定输出。虽然这是一个可行的解决方法,但它意味着要降低性能,并在不需要的地方向数据库添加其他过程。

我需要一种获取正确结果集描述的方法,因为这是一个罕见的调用,我可以在这里提高性能,而不必更改主过程本身。

非常感谢您收到任何选项。

0 个答案:

没有答案