sqlserver 递归

发布时间 2023-09-21 15:36:50作者: pandora2050

需求:树状结构的产品BOM图,每个节点表示一个物料,需要输出物料层级间的关系。

 效果如下:

1、构建SQLserver中可以递归的结果集语句;

select a.wo_wlid,b.wobom_wlid from jserp.wo a,jserp.wobom b
where a.wo_zlh='60585480_50' and a.wo_woid=b.wobom_woid

2、将上面的结果集作为数据源进行递归;

with cte as(
select a.wo_woid,a.wo_zlh,a.wo_wlid,b.wobom_wlid,cast(rtrim(a.wo_wlid) as varchar(max)) as WLPath from jserp.wo a,jserp.wobom b
where a.wo_zlh='60585480_50' and a.wo_woid=b.wobom_woid and a.wo_wlid='110102000581' 
union all
select a.wo_woid,a.wo_zlh,a.wo_wlid,a.wobom_wlid,cte.WLPath+'->'+rtrim(a.wo_wlid) from 
(select a.wo_woid,a.wo_zlh,a.wo_wlid,b.wobom_wlid from jserp.wo a,jserp.wobom b
where a.wo_zlh='60585480_50' and a.wo_woid=b.wobom_woid) a
inner join cte  on cte.wobom_wlid=a.wo_wlid
)
select WLPath+'->'+rtrim(wobom_wlid) as WLPath from cte where wo_wlid<>'110102000581' 

3、sqlserver递归注意点:
  1.union all可以重复查询,union有distinct作用,会自动去除重复行,用在递归语句中,本身会报错,就算不报错也不会继续向下递归,必须使用union all;
  2.CTE(Common Table Expression,公用表达式)是一种临时命名结果集,在递归语句中,作为主表使用,cte指向子节点的物料ID和从表节点的物料ID建立关联
  3.注意可能存在的报错
    报错:在递归查询 "cte" 的列 "WLPath" 中,定位点类型和递归部分的类型不匹配。
    原因:由于字段 wo_wlid 递归循环,而表wo中的wo_wlid字段长度不够,所以必须将wo_wlid字符串长度设置为max或8000。
  4.本例子中,WLPath字段长度要小于8000,不能无限递归。