简体   繁体   中英

How to use #tmp Table in Loop in Recursive Function

I am trying to create a loop that when given a part id, it will search a table of assembly parts and explode all the parts into a large list.

It needs to be recursive because Part 123 may have parts 1, 2, 3, 4, 5 and parts 4 and 5 are also assembly items. I thought I had come up with something pretty good and easily returns the part id and the part level for each item. Then I find out that I can't use temp tables, so it shoots my loop down.

What can I use in place of the temp table to give me the same function here?

CREATE FUNCTION [dbo].[fn_getParts] (
    @source_part_id int
    , @level int
)
RETURNS @parts_list TABLE (
    [part]  int NOT NULL,
    [level] int NOT NULL
)
AS 
BEGIN
    DECLARE
        @max    int = 0,
        @cnt    int = 0,
        @PID    int = 0, 
        @Plvl   int = 0,
        @id     int = 0


    INSERT INTO @parts_list VALUES (@source_part_id, @level)

    SET @level += 1

    SELECT [Comp_Part_ID] AS [PID], @level AS [level]
    INTO #chkParts
    FROM [assemblies]
    WHERE [Assy_PID] = @source_part_id

    SELECT @max = COUNT(*) FROM #chkParts
    WHILE @cnt <= @max
    BEGIN
        SELECT @PID = [PID], @Plvl = [level] FROM #chkParts
        INSERT INTO @parts_list
            SELECT * FROM [fn_getParts](@PID, @Plvl)
        SET @cnt += 1
    END

    RETURN
END

Here's some sample data:

CREATE TABLE [Assemblies] (
  [PartID] int,
  [Comp_PartID] int
  )
  
  INSERT INTO [Assemblies] VALUES
  (1,2),
  (1,3),
  (1,4),
  (1,5),
  (1,6),
  (3,9),
  (3,10),
  (10,11),
  (10,23),
  (10,24),
  (10,31),
  (11,24),
  (11,23)

If I enter SELECT * FROM [fn_getParts](1,0) I would expect the following:

part,level
1,0
2,1
3,1
4,1
9,2
10,2
11,3
23,3
24,3

The code can be simplified somewhat by wrapping an Inline Table-Valued Function around a Recursive CTE, eg:

create function dbo.fn_getParts (
    @source_part_id int
)
returns table as return (
    with PartsHierarchy as (
      select @source_part_id as part, 0 as level
      union all
      select Comp_PartID, 1 + level
      from Assemblies
      join PartsHierarchy on part = PartID
    )
    select part, level
    from PartsHierarchy
);

And then, invoking it for different part numbers...

select * from dbo.fn_getParts(1);
part level
---- ----
   1    0
   2    1
   3    1
   4    1
   5    1
   6    1
   9    2
  10    2
  11    3
  23    3
  24    3
  31    3
  24    4
  23    4
select * from dbo.fn_getParts(10);
part level
---- -----
  10    0
  11    1
  23    1
  24    1
  31    1
  24    2
  23    2
select * from dbo.fn_getParts(11);
part level
---- -----
  11    0
  24    1
  23    1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM