PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Phát hiện các mục trùng lặp trong CTE đệ quy

Từ dep trong truy vấn thứ hai (sau union ) là mơ hồ. Trên thực tế, nó được hiểu là cột của rdeps , không phải là bí danh của objectdependencies.

with recursive rdeps as (
  select dep
  from objectdependencies dep
  where dep.dependson = 4 -- starting point
  union all
  select dep -- this means r.dep
  from objectdependencies dep
  join rdeps r
    on (r.dep).id = dep.dependson
) select (dep).id from rdeps;

Đây là lý do tại sao truy vấn tạo ra một vòng lặp vô tận. Bạn có thể sửa lỗi này bằng cách thay đổi bí danh:

with recursive rdeps as (
  select dep
  from objectdependencies dep
  where dep.dependson = 4 -- starting point
  union all
  select objectdep
  from objectdependencies objectdep
  join rdeps r
    on (r.dep).id = objectdep.dependson
) select (dep).id from rdeps;

 id 
----
  1
  2
  3
  1
  2
  1
(6 rows)    

Hoặc tốt hơn, chỉ bằng cách sử dụng các cột, giống như Chúa nhân lành đã định:

with recursive rdeps as (
    select id, dependson
    from objectdependencies
    where dependson = 4
union all
    select d.id, d.dependson
    from objectdependencies d
    join rdeps r
    on r.id = d.dependson
) 
select *
from rdeps;

Truy vấn đầu tiên trong câu hỏi là tất cả những gì bạn có thể làm trong sql đơn giản vì không có giao tiếp giữa các nhánh (paralel) khác nhau được tạo bởi truy vấn đệ quy. Trong cách tiếp cận chức năng, bạn có thể sử dụng một bảng tạm thời như một cửa hàng chung cho tất cả các chi nhánh. Hàm có thể trông như thế này:

create or replace function rec_function(int)
returns void language plpgsql as $$
declare
    i int;
begin
    for i in
        select id
        from objectdependencies
        where dependson = $1
    loop
        if not exists(
            select from temp_table 
            where id = i)
        then
            insert into temp_table values(i);
            perform rec_function(i);
        end if;
    end loop;
end $$;

Cách sử dụng:

create temp table temp_table(id int);

select rec_function(4);

select *
from temp_table;


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. '$$' được sử dụng để làm gì trong PL / pgSQL

  2. Postgres - TẠO BẢNG TỪ CHỌN

  3. Khối mã ẩn danh PL / pgSQL

  4. Postgres không sử dụng chỉ mục khi quét chỉ mục là tùy chọn tốt hơn nhiều

  5. PostgreSQL multi INSERT ... RETURNING với nhiều cột