如何在递归函数的循环中使用#tmp Table

How to use #tmp Table in Loop in Recursive Function

我正在尝试创建一个循环,当给定零件 ID 时,它会搜索 table 个装配零件并将所有零件展开到一个大列表中。

需要递归,因为123部分可能有1、2、3、4、5部分,4、5部分也是装配项。 我以为我想出了一些非常好的东西,并且很容易 returns 每个项目的零件 ID 和零件级别。然后我发现我不能使用 temp tables,所以它会降低我的循环。

我可以用什么代替临时 table 来给我同样的功能?

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

下面是一些示例数据:

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)

如果我输入 SELECT * FROM [fn_getParts](1,0),我会得到以下结果:

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

通过将内联 Table 值函数包装在递归 CTE 周围,可以稍微简化代码,例如:

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
);

然后,为不同的部件号调用它...

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