使用CTE递归的SQL标量函数问题

时间:2012-06-14 16:22:04

标签: sql function recursion common-table-expression

我正在尝试创建一个返回nvarchar(MAX)字符串的SQL函数。该函数使用CTE递归WITH语句。当它们不在函数中时我可以让所有部件正常工作但是当我把它们放在一起时我得到以下错误:

Msg 208,Level 16,State 1,Line 1 无效的对象名称'drillUp'。

在“编译”期间,函数本身不会出错,但仅在运行时才会出错。 如果我将SET @RET更改为“TESTING ...”而不是调用SELECT语句,它将按预期运行。

我对SQL很新,我不确定我做错了什么。如果有人能给我一些建议我会非常感激。

谢谢。

CREATE FUNCTION BuildName(@SUBTRAIT_ID int)
RETURNS nvarchar(MAX)
AS
BEGIN
DECLARE @RET nvarchar(MAX)
DECLARE @TEXTMODE nvarchar(50)
DECLARE @PARENTID int
DECLARE @CHECKDROPDOWN TABLE
(
    TextMode nvarchar(MAX),
    ParentId int
);

WITH drillUp(FullName, ParentId, depth) 
AS
(
    SELECT  
        SubValue,
        ParentId,
        0           
    FROM SubTrait
    WHERE Id = @SUBTRAIT_ID 
    UNION ALL
    SELECT                  
        child.SubValue + ' -> ' + drillUp.FullName,
        child.ParentId,
        drillUp.depth + 1
    FROM SubTrait child, drillUp
    WHERE drillUp.ParentId = child.Id 
)


INSERT @CHECKDROPDOWN 
SELECT TextMode, ParentId FROM SubTrait WHERE Id = @SUBTRAIT_ID

SET @TEXTMODE = (SELECT MAX(TextMode) FROM @CHECKDROPDOWN);
SET @PARENTID = (SELECT MAX(ParentId) FROM @CHECKDROPDOWN);

IF (@TEXTMODE != 'DropDown')
BEGIN
    SET @SUBTRAIT_ID = @PARENTID
END 

SET @RET = (
       SELECT FullName
       FROM drillUp du
       WHERE depth =(SELECT MAX(depth) FROM drillUp ) - 1
     )
--  SET @RET = 'TESTING...'

RETURN (@RET)

END;
GO


PRINT dbo.BuildName(77)

1 个答案:

答案 0 :(得分:1)

CTE仅适用于遵循其定义的声明。因此,您应该将SET @RET移至drillup的定义:

CREATE FUNCTION BuildName(@SUBTRAIT_ID int)
RETURNS nvarchar(MAX)
AS
BEGIN
DECLARE @RET nvarchar(MAX)
DECLARE @TEXTMODE nvarchar(50)
DECLARE @PARENTID int
DECLARE @CHECKDROPDOWN TABLE
(
    TextMode nvarchar(MAX),
    ParentId int
);

INSERT @CHECKDROPDOWN 
SELECT TextMode, ParentId FROM SubTrait WHERE Id = 74

SET @TEXTMODE = (SELECT MAX(TextMode) FROM @CHECKDROPDOWN);
SET @PARENTID = (SELECT MAX(ParentId) FROM @CHECKDROPDOWN);

IF (@TEXTMODE != 'DropDown')
BEGIN
    SET @SUBTRAIT_ID = @PARENTID
END 

WITH drillUp(FullName, ParentId, depth) 
AS
(
    SELECT  
        SubValue,
        ParentId,
        0           
    FROM SubTrait
    WHERE Id = @SUBTRAIT_ID 
    UNION ALL
    SELECT                  
        child.SubValue + ' -> ' + drillUp.FullName,
        child.ParentId,
        drillUp.depth + 1
    FROM SubTrait child, drillUp
    WHERE drillUp.ParentId = child.Id 
)
SELECT @RET = (
       SELECT FullName
       FROM drillUp du
       WHERE depth =(SELECT MAX(depth) FROM drillUp ) - 1
     )
--  SET @RET = 'TESTING...'


RETURN (@RET)

END;
GO


PRINT dbo.BuildName(77)