存储过程中的递归

时间:2013-11-01 20:24:27

标签: sql sql-server sql-server-2008 recursion recursive-query

嘿伙计们,我有一个存储过程,最近由一位正在度假的同事修改过,我在递归SQL方面的经验非常有限。我目前正在接受:

  

在语句完成之前,最大递归100已用尽

有什么想法吗?

ALTER PROCEDURE [dbo].[SP_BOM_GetRawMBOM]
   @JobNo varchar(20),
   @ImportNo int = NULL
AS
BEGIN
SET NOCOUNT ON

IF @ImportNo IS NULL 
       SELECT @ImportNo = MAX(ImportNo) 
       FROM Import 
       WHERE JobNo = @JobNo AND SourceType = 'MBOM'

--Can't have aggregates in recursive portion of the common table,
--so get what we need to filter and inner join.
SELECT Drawing, MAX(ImportNo) AS ImportNo
INTO #DrawingImportNo 
FROM RawMBOM
WHERE 
    JobNo = @JobNo AND
    ImportNo <= @ImportNo AND
    Drawing NOT LIKE '_3_2_'
GROUP BY Drawing

SET NOCOUNT OFF

;WITH  Mbom AS (
    --Top (Skid) Level
    SELECT
        S.JobNo, 
        S.ImportNo, 
        CAST('»'+RTRIM(S.Drawing) AS varchar(500)) AS KeyField,
        S.Drawing AS Skid,
        S.Drawing,
        S.Drawing AS PartKey,  
        S.PartNo,
        S.Description,
        S.Qty,
        S.PartSize,
        S.PartLength,
        S.Material,
        S.CutLength,
        S.Ported,
        S.Rev,
        S.IsSub
    FROM    RawMbom S
        INNER JOIN #DrawingImportNo D ON D.Drawing = S.Drawing AND D.ImportNo = S.ImportNo 
    WHERE   
        JobNo = @JobNo AND
        RTRIM(PartKey) = '' AND
        NOT EXISTS (SELECT PartKey FROM RawMBOM WHERE JobNo = @JobNo AND ImportNo <= @ImportNo AND PartKey = S.Drawing)
    UNION ALL
    --Recursive parts and subassemblies
    SELECT
        R.JobNo, 
        R.ImportNo, 
        CAST(RTRIM(U.KeyField)+'»'+R.PartKey AS varchar(500)) AS KeyField,
        U.Skid,
        R.Drawing,
        R.PartKey,
        R.PartNo,
        R.Description,
        U.Qty * R.Qty AS Qty,
        R.PartSize,
        R.PartLength,
        R.Material,
        R.CutLength,
        R.Ported,
        R.Rev,
        R.IsSub
    FROM    RawMbom R
        INNER JOIN Mbom AS U ON R.Drawing = U.PartKey
        INNER JOIN #DrawingImportNo D ON D.Drawing = R.Drawing AND D.ImportNo = R.ImportNo
)
SELECT * FROM Mbom 
WHERE
    RTRIM(PartKey) <> '' AND IsSub = 0 AND --Remove assemblies from the mix
    UPPER(LEFT(PartNo,3)) <> 'REF'  AND --Don't pass because it is on ELT or EBOM
    (
        (DATALENGTH(RTRIM(PartSize))>0)  OR
        (DATALENGTH(RTRIM(PartLength))>0) OR
        (DATALENGTH(RTRIM(Material))>0)  OR
        (DATALENGTH(RTRIM(PartNo))>0)  
    ) -- Don't pass on blank parts.

DROP TABLE #DrawingImportNo
END

1 个答案:

答案 0 :(得分:0)

通过@HABO,我能够为查询的深度添加限制。这将允许我更正确地运行和调试它。

为此,HABO的回答超过here

对于那些懒得点击的人来说,细节是你将深度或级别列添加到主要功能并在递归部分中增加它。 新查询,突出显示:

BEGIN

SET NOCOUNT ON

IF @ImportNo IS NULL SELECT @ImportNo = MAX(ImportNo) FROM Import WHERE JobNo = @JobNo AND SourceType = 'MBOM'

--Can't have aggregates in recursive portion of the common table,
--so get what we need to filter and inner join.
SELECT Drawing, MAX(ImportNo) AS ImportNo
INTO #DrawingImportNo 
FROM RawMBOM
WHERE 
    JobNo = @JobNo AND
    ImportNo <= @ImportNo AND
    -- Work instruction P.25 x3x2x is a drawing for a prefabricated vessel.
    --Parts do not get processed in the BOM because parts come as
    --part of the vessel.  Example - Site Glasses
    Drawing NOT LIKE '_3_2_'
GROUP BY Drawing

SET NOCOUNT OFF

;WITH  Mbom AS (
    --Top (Skid) Level
    SELECT
        S.JobNo, 
        S.ImportNo, 
        CAST('»'+RTRIM(S.Drawing) AS varchar(500)) AS KeyField,
        S.Drawing AS Skid,
        S.Drawing,
        S.Drawing AS PartKey,  
        S.PartNo,
        S.Description,
        S.Qty,
        S.PartSize,
        S.PartLength,
        S.Material,
        S.CutLength,
        S.Ported,
        S.Rev,
        S.IsSub
        ,1 Depth
    FROM    RawMbom S
        INNER JOIN #DrawingImportNo D ON D.Drawing = S.Drawing AND D.ImportNo = S.ImportNo 
    WHERE   
        JobNo = @JobNo AND
        RTRIM(PartKey) = '' AND
        NOT EXISTS (SELECT PartKey FROM RawMBOM WHERE JobNo = @JobNo AND ImportNo <= @ImportNo AND PartKey = S.Drawing)
    UNION ALL
    --Recursive parts and subassemblies
    SELECT
        R.JobNo, 
        R.ImportNo, 
        CAST(RTRIM(U.KeyField)+'»'+R.PartKey AS varchar(500)) AS KeyField,
        U.Skid,
        R.Drawing,
        R.PartKey,
        R.PartNo,
        R.Description,
        U.Qty * R.Qty AS Qty,
        R.PartSize,
        R.PartLength,
        R.Material,
        R.CutLength,
        R.Ported,
        R.Rev,
        R.IsSub
        ,Depth + 1
    FROM    RawMbom R
        INNER JOIN Mbom AS U ON R.Drawing = U.PartKey
        INNER JOIN #DrawingImportNo D ON D.Drawing = R.Drawing AND D.ImportNo = R.ImportNo
    WHERE Depth < 10
)
SELECT * FROM Mbom 
WHERE
    RTRIM(PartKey) <> '' AND IsSub = 0 AND --Remove assemblies from the mix
    UPPER(LEFT(PartNo,3)) <> 'REF'  AND --Don't pass because it is on ELT or EBOM
    (
        (DATALENGTH(RTRIM(PartSize))>0)  OR
        (DATALENGTH(RTRIM(PartLength))>0) OR
        (DATALENGTH(RTRIM(Material))>0)  OR
        (DATALENGTH(RTRIM(PartNo))>0)  
    ) -- Don't pass on blank parts.

DROP TABLE #DrawingImportNo
END