PostgreSQL中的游标循环

4
我们有一个用pl/sql(oracle)编写的函数如下所示:
CREATE OR REPLACE PROCEDURE folder_cycle_check (folder_key IN NUMBER, new_parent_folder_key IN NUMBER) IS
    parent_of_parent NUMBER;
    ILLEGAL_CYCLE EXCEPTION;
    CURSOR parent_c IS
    SELECT parent_folder_key FROM folder
        WHERE folder_key = new_parent_folder_key;
BEGIN

IF folder_key = new_parent_folder_key THEN
    RAISE ILLEGAL_CYCLE;
END IF;

FOR parent_rec IN parent_c LOOP
    BEGIN folder_cycle_check(folder_key, parent_rec.parent_folder_key); END;
END LOOP;

END;

现在,我需要使用pl/pgsql(PostgreSQL)重新编写相同的过程,以实现类似的功能。请帮助我并发送该pl/pgsql函数。

编辑(来自评论的格式化代码)

CREATE OR REPLACE FUNCTION folder_cycle_check(IN folder_key INTEGER, IN new_parent_folder_key INTEGER) 
  RETURNS VOID 
AS $procedure$ 
   DECLARE parent_of_parent INTEGER; 
   PARENT_C CURSOR FOR 
        SELECT parent_folder_key 
        FROM folder 
        WHERE folder_key = new_parent_folder_key; 
BEGIN 
    IF folder_key = new_parent_folder_key THEN 
        RAISE EXCEPTION 'ILLEGAL_CYCLE'; 
    END IF

    FOR parent_rec IN (SELECT parent_folder_key FROM folder WHERE folder_key = new_parent_folder_key) LOOP 
        PERFORM folder_cycle_check(folder_key,parent_rec.parent_folder_key); 
    END LOOP; 

    RETURN; 
END; 
$procedure$ 
LANGUAGE plpgsql;    

你的Postgres解决方案有编译器错误吗?如果是,请将它们与你的Postgres代码一起发布。 - user330315
1
你的尝试是什么?请记住,这不是一个“请替我完成工作”的网站。你必须展示一些尝试 - 我们不会在这里喂食。 - Bohemian
感谢Bohemian的友好回复。这是我的尝试。CREATE OR REPLACE FUNCTION folder_cycle_check(IN folder_key INTEGER, IN new_parent_folder_key INTEGER) RETURNS VOID AS $procedure$ DECLARE parent_of_parent INTEGER; PARENT_C CURSOR FOR SELECT parent_folder_key FROM folder WHERE folder_key = new_parent_folder_key; BEGIN IF folder_key = new_parent_folder_key THEN RAISE EXCEPTION 'ILLEGAL_CYCLE'; END IF - vchitta
FOR parent_rec IN(SELECT parent_folder_key FROM folder WHERE folder_key = new_parent_folder_key) LOOP PERFORM folder_cycle_check(folder_key,parent_rec.parent_folder_key); END LOOP; RETURN; END; $procedure$ LANGUAGE plpgsql; - vchitta
我怀疑我根本没有进入for循环。我在for循环内放置了一个调试语句,如RAISE NOTICE或RAISE EXCEPTION 'Hi',但也没有捕获到。该函数的基本目的是检查是否将父文件夹复制(分配为子文件夹)到其自身的子文件夹中。如果是,则引发异常。我在使用游标的FOR循环方面错了吗?建议。 - vchitta
@vchitta 请不要在评论中发表评论,而是编辑您的问题。 - Milen A. Radev
1个回答

15

这应该可以工作:

CREATE OR REPLACE FUNCTION folder_cycle_check (p_folder_key INT4, p_new_parent_folder_key INT4) RETURNS VOID AS $$
DECLARE
    v_parent_rec RECORD;
BEGIN
    IF folder_key = new_parent_folder_key THEN
        RAISE EXCEPTION 'ILLEGAL_CYCLE';
    END IF;
    FOR v_parent_rec IN SELECT parent_folder_key FROM folder WHERE folder_key = p_new_parent_folder_key LOOP
        PERFORM folder_cycle_check(folder_key, v_parent_rec.parent_folder_key)
    END LOOP;
    RETURN;
END;
$$ LANGUAGE plpgsql;

1
但是对于PostgreSQL,我们应该使用FUNCTION而不是PROCEDURE。 - vchitta

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接