使用游标多次更新 pgsql
multiple update pgsql using cursor
这段代码没有错误,但没有任何数据变化,请帮助我。我想从一些库存 table
中多次更新数量
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$
我修改了你的函数以使其更短并使用 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。
你不需要循环。单个 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;
有些场景需要游标。例如,假设您正在更新 1000 万行,并且在第 6 百万条记录处抛出异常,更新将失败,然后它将回滚失败之前更新的所有行。如果使用游标,速度会变慢,但您可以更好地控制该过程,并能够绕过错误并继续发布更新。但是话又说回来,您的里程数可能会有所不同...
这段代码没有错误,但没有任何数据变化,请帮助我。我想从一些库存 table
中多次更新数量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$
我修改了你的函数以使其更短并使用 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。
你不需要循环。单个 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;
有些场景需要游标。例如,假设您正在更新 1000 万行,并且在第 6 百万条记录处抛出异常,更新将失败,然后它将回滚失败之前更新的所有行。如果使用游标,速度会变慢,但您可以更好地控制该过程,并能够绕过错误并继续发布更新。但是话又说回来,您的里程数可能会有所不同...