Domanda

Hey guys I got a stored procedure that was recently modified by a co-worker who is on vacation, my experience in recursive SQL is quite limited. I am currently getting:

The maximum recursion 100 has been exhausted before statement completion

Any ideas?

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
È stato utile?

Soluzione

Via @HABO, I was able to add limitation to the depth of the query. This will allow me to run and debug it more properly.

For this, HABO has an answer over here.

For those too lazy to click over, the detail is that you add a depth or level column to the primary function and increment it in the recursive section. New query, with highlights:

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top