2012-06-14 21 views
0

我正在尝试使SQL函数返回一个nvarchar(MAX)字符串。该函数使用CTE递归WITH语句。当它们不在功能中时,我可以使所有部件正常工作,但是当我将它们放在一起时,出现以下错误:使用CTE递归的SQL缩放功能问题

消息208,级别16,状态1,行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

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) 
+0

你确定你感动了正确的事情?在OP的例子中,你有CTE使用'@ SUBTRAIT_ID',然后改变'@ SUBTRAIT_ID'中的值,然后使用CTE查询。我认为CTE需要转移到SET,而不是SET转移到CTE? – MatBailie

+0

@Dems - 你是对的,我更新了我的回答以反映你的评论 – Lamak

+0

非常感谢!这是问题所在。不过,我还需要将'SET @RET = ...'更改为'SELECT @RET = ...'。再次感谢! Joe – Joe