在psql上使用游标递归,没有找到任何数据

时间:2017-03-06 03:10:42

标签: postgresql plpgsql

如何使用递归查询然后使用游标更新postgresql中的多行。我尝试返回数据但没有找到数据。使用递归查询和光标的任何替代方法,或者更好的代码请帮助我。

drop function proses_stock_invoice(varchar, varchar, character varying);

create or replace function proses_stock_invoice
    (p_medical_cd varchar,p_post_cd varchar, p_pstruserid character varying)
returns void
language plpgsql
as $function$
declare
    cursor_data refcursor;
    cursor_proses refcursor;
    v_medicalCd varchar(20);
    v_itemCd varchar(20);
    v_quantity numeric(10);
begin
    open cursor_data for 
        with recursive hasil(idnya, level, pasien_cd, id_root) as (
            select medical_cd, 1, pasien_cd, medical_root_cd
            from trx_medical
            where medical_cd = p_pstruserid
        union all 
            select A.medical_cd, level + 1, A.pasien_cd, A.medical_root_cd
            from trx_medical A, hasil B
            where A.medical_root_cd = B.idnya
        )
        select idnya from hasil where level >=1;
    fetch next from cursor_data into v_medicalCd;
    return v_medicalCd;

    while (found)
    loop
        open cursor_proses for 
            select B.item_cd, B.quantity from trx_medical_resep A
            join trx_resep_data B on A.medical_resep_seqno = B.medical_resep_seqno
        where A.medical_cd = v_medicalCd and B.resep_tp = 'RESEP_TP_1';
        fetch next from cursor_proses into v_itemCd, v_quantity;
        while (found)
        loop
            update inv_pos_item
            set quantity = quantity - v_quantity, modi_id = p_pstruserid, modi_id = now()
            where item_cd = v_itemCd and pos_cd = p_post_cd;
        end loop;
        close cursor_proses;
    end loop;
    close cursor_data;
end 
$function$;

但没有找到任何数据?

1 个答案:

答案 0 :(得分:0)

您有return void的功能,因此它永远不会向您返回任何数据。从第一个光标获取第一个记录后,你仍然有return v_medicalCd语句,因此该函数将从该点返回,并且永远不会到达下面的行。

在分析你的函数时,你有(1)一个从表idnya产生一些trx_medical值的游标,这是为(2)一个产生{{1}的游标的游标输入的每个v_itemCd, v_quantity从表trx_medical_resep, trx_resep_data开始,然后用于(3)更新表idnya中的某些行。你不需要游标就可以做到这一点,实际上它非常低效。相反,将整个事物转换为单个更新语句。

我在这里假设您想要通过从库存中的库存中减去向患者开出的药物来更新药品库存。这意味着您必须按医学类型总结规定的数量。这应该是这样的(注意评论):

inv_pos_item

重要

与所有UPDATE语句一样,在运行该函数之前测试此代码。您可以通过单独运行CREATE FUNCTION proses_stock_invoice -- VVV parameter not used (p_medical_cd varchar, p_post_cd varchar, p_pstruserid varchar) RETURNS void AS $function$ UPDATE inv_pos_item -- VVV column repeated VVV SET quantity = quantity - prescribed.quantity, modi_id = p_pstruserid, modi_id = now() FROM ( WITH RECURSIVE hasil(idnya, level, pasien_cd, id_root) AS ( SELECT medical_cd, 1, pasien_cd, medical_root_cd FROM trx_medical WHERE medical_cd = p_pstruserid UNION ALL SELECT A.medical_cd, level + 1, A.pasien_cd, A.medical_root_cd FROM trx_medical A, hasil B WHERE A.medical_root_cd = B.idnya ) SELECT B.item_cd, sum(B.quantity) AS quantity FROM trx_medical_resep A JOIN trx_resep_data B USING (medical_resep_seqno) JOIN hasil ON A.medical_cd = hasil.idnya WHERE B.resep_tp = 'RESEP_TP_1' --AND hacil.level >= 1 Useless because level is always >= 1 GROUP BY 1 ) prescribed WHERE item_cd = prescribed.item_cd AND pos_cd = p_post_cd; $function$ LANGUAGE sql STRICT; 子查询作为独立查询来确保它做正确的事情。