我有2个表:Document和DocumentLink。 DocumentLink有两个字段:MainDocID和LinkedDocID,它们填充了Document表中的DocID值。每个DocID都可以在两个字段中。
例如:
MainDocID LinkedDocID
317 3214
7969 317
317 11723
317 17387
7969 19325
19325 19847
我写了一个返回所有链接的DocID的程序。对于我的示例中的任何DocID相同的结果:
317
3214
7969
11723
17387
19325
19847
这是程序:
CREATE PROCEDURE [dbo].[GetAllLinkedDocumentsForStack](@DocID int) AS BEGIN
create table #doc_tree (id int IDENTITY (1, 1) NOT NULL ,
doc_id int NULL ,
isdone int NOT NULL DEFAULT (0)
) ON [PRIMARY]
insert into #doc_tree (doc_id) values (@DocID)
declare @id_header int
set @id_header = @DocID
declare c0 cursor for select doc_id from #doc_tree where isdone = 0
open c0
fetch next from c0 into @id_header
while @@fetch_status=0
begin
insert into #doc_tree (doc_id)
select LinkedDocID from DocumentLink where MainDocID = @id_header and LinkedDocID not in (select doc_id from #doc_tree)
union
select MainDocID from DocumentLink where LinkedDocID = @id_header and MainDocID not in (select doc_id from #doc_tree);
update #doc_tree set isdone = 1 where doc_id = @id_header
fetch next from c0 into @id_header
end
close c0
deallocate c0
select DocID from Document where DocID In (select Doc_ID from #doc_tree)
drop table #doc_tree END
我的问题:我如何对CTE做同样的事情?
答案 0 :(得分:1)
这对CTE来说有点棘手。走过图表时的关键是找到一种方法来防止无限循环。这需要将它们填充到字符串中并检查字符串以防止无限循环的方法:
with cte as (
select @docid as docid,
cast(',' + cast(@docid as varchar(max)) + ',' as varchar(max)) as list
union all
select maindocid, cast(list + maindocid + ',' as varchar(max))
from DocumentLink dl join
cte
on dl.linkeddocid = cte.docid
where cte.list not like '%,' + dl.maindocid + ',%'
union all
select linkeddocid, cast(list + linkeddocid + ',' as varchar(max))
from DocumentLink dl join
cte
on dl.maindocid = cte.docid
where cte.list not like '%,' + dl.linkeddocid + ',%'
)
select docid
from cte;
另请注意,有两个递归组件,一个用于在列表中单向行走。