使用游标多次更新pgsql

时间:2017-02-02 06:11:31

标签: sql postgresql sql-update cursor plpgsql

此代码没有错误,但没有数据更改请帮助我。我想从一些股票表中多次更新数量

drop FUNCTION SP_PROSES_STOCK(noresep bigint, p_post_cd varchar);
CREATE or replace FUNCTION SP_PROSES_STOCK(noresep bigint, p_post_cd varchar)
RETURNS void
LANGUAGE plpgsql
as $function$
DECLARE cursorData refcursor;
    v_item_cd varchar;
    v_quantity numeric;

begin

open cursorData FOR
select A.item_cd, A.quantity from trx_medical_resep B
inner join trx_resep_data A on A.medical_resep_seqno = B.medical_resep_seqno
where B.medical_resep_seqno = noresep; 
fetch next from cursorData into v_item_cd,v_quantity;
while (found)
loop
    update inv_pos_item set quantity = quantity - v_quantity 
    where item_cd = v_item_cd and pos_cd = p_post_cd;
end loop;
close cursorData;

END 
$function$

3 个答案:

答案 0 :(得分:2)

我改进了你的功能,使其缩短并使用FOR。我还添加了RAISE NOTICE进行调试。你能尝试一下吗?

CREATE or replace FUNCTION SP_PROSES_STOCK(noresep bigint, p_post_cd varchar)
RETURNS void
LANGUAGE plpgsql
as $function$
DECLARE v_cursor record;

BEGIN

   FOR v_cursor IN
       SELECT A.item_cd,
              A.quantity
         FROM trx_medical_resep B
         JOIN trx_resep_data A ON A.medical_resep_seqno = B.medical_resep_seqno
        WHERE B.medical_resep_seqno = noresep
   LOOP
       RAISE NOTICE 'Changes for %', v_curosr; 
       UPDATE inv_pos_item
           SET quantity = quantity - v_cursor.quantity 
         WHERE item_cd = v_cursor.item_cd
           AND pos_cd = p_post_cd;
   END LOOP;
END 
$function$

调试完成后,您可以删除RAISE NOTICE。

答案 1 :(得分:0)

你不需要循环。单个UPDATE语句会快得多:

CREATE or replace FUNCTION SP_PROSES_STOCK(noresep bigint, p_post_cd varchar)
  RETURNS void
as 
$function$
begin

  update inv_pos_item 
     set quantity = quantity - v.quantity 
  from (
    select A.item_cd, A.quantity 
    from trx_medical_resep B
      join trx_resep_data A on A.medical_resep_seqno = B.medical_resep_seqno
    where B.medical_resep_seqno = noresep
  ) v
  where item_cd = v.item_cd and pos_cd = p_post_cd;

END;
$function$
LANGUAGE plpgsql;

答案 2 :(得分:0)

在某些情况下需要使用游标。例如,假设您要更新1000万行,并且在第600万条记录中引发异常,则更新将失败,然后它将回滚失败之前已更新的所有行。如果使用了游标,它将变慢,但是您将对过程有更大的控制,并且能够绕过错误并继续发布更新。但是话说回来,您的里程可能会有所不同...