Sql server SQL中的递归查询
我有两个表:Document和DocumentLink。 DocumentLink有两个字段:MainDocID和LinkedDocID,它们用文档表中的DocID值填充。每个DocID可以在两个字段中 例如:Sql server SQL中的递归查询,sql-server,Sql Server,我有两个表:Document和DocumentLink。 DocumentLink有两个字段:MainDocID和LinkedDocID,它们用文档表中的DocID值填充。每个DocID可以在两个字段中 例如: MainDocID LinkedDocID 317 3214 7969 317 317 11723 317 17387 7969 19325 19325 19847 我编写了返回所有链接文档ID的过程。对于我的示例中的
MainDocID LinkedDocID
317 3214
7969 317
317 11723
317 17387
7969 19325
19325 19847
我编写了返回所有链接文档ID的过程。对于我的示例中的任何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进行同样的操作 这对于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;
还请注意,有两个递归组件,一个用于遍历列表。系统中是否存在循环引用的可能性(可能是错误或预期行为)?您是指2条记录,例如317 3214和3214 317?不,这更可能发生在连锁店:1,25-25258-258,98-981908-1908,1。这不可能吗?不可能发生这种情况?客户根据现有文档创建文档,但不排除这种情况