你的功能,从根本上简化:
CREATE OR REPLACE FUNCTION ccdb_dummy.o_payments1(a integer)
RETURNS void
LANGUAGE plpgsql AS
$func$
DECLARE
t record;
t1 record;
BEGIN
FOR t IN
SELECT *
, nextval('ccdb_stg.payments_seq') AS payment_no
, c.cin
FROM ccdb_stg.o_payments_stg p
LEFT JOIN ccdb_dummy.consumers c USING (consumer_num)
WHERE p.section_code = $1
LOOP
INSERT INTO ccdb_dummy.payments(payment_id,receipt_id,source_system_flag,cin, ... ,pm_amount,ref_transaction_id,creation_dt,created_by)
VALUES(t.payment_no,t.receipt_id,t.origin_flag,t.cin, ... ,t.pm_amount,null,now(),'system');
FOR t1 IN
SELECT *
FROM ccdb_stg.o_payment_head_dtls_stg h
WHERE h.mbc_receipt_id = t.receipt_id
LOOP
INSERT INTO ccdb_dummy.payment_head_dtls(payment_id,mbc_receipt_id,charge_head_code,amount,tariff_id,creation_dt,created_by)
VALUES (t.payment_no,t1.mbc_receipt_id,t1.charge_head_code,t1.amount,t1.tariff_id,now(),'system');
END LOOP;
END LOOP;
END
$func$;
-
使用 a 的隐式游标FOR LOOP
而不是笨重的显式游标加上冗余计数和循环。Much更简单、更快。阅读手册中的“循环查询结果”一章 https://www.postgresql.org/docs/current/plpgsql-control-structures.html#PLPGSQL-RECORDS-ITERATING.
-
LEFT JOIN
to ccdb_dummy.consumers
在第一个SELECT
而不是为每一行运行单独的选择。
-
还包括nextval('ccdb_stg.payments_seq') AS payment_no
在第一个SELECT
。比许多单独的查询便宜。
但这还远非完美。考虑一种全新的方法基于集合的操作而不是循环中的单独插入。但更干净、更快。这就是现代 RDBMS 的最佳运行方式。
One具有数据修改 CTE 的 SQL 语句
包装到 SQL 函数中以作为直接替换。
数据修改 CTE https://www.postgresql.org/docs/current/queries-with.html#QUERIES-WITH-MODIFYING需要 Postgres9.1或稍后。
CREATE OR REPLACE FUNCTION ccdb_dummy.o_payments2(integer)
RETURNS void
LANGUAGE sql AS
$func$
WITH ins1 AS (
INSERT INTO ccdb_dummy.payments(
payment_id, cin, receipt_id, ... , pm_amount, ref_transaction_id,creation_dt,created_by)
SELECT nextval('ccdb_stg.payments_seq'),c.cin,p.receipt_id, ... , p.pm_amount, null, now(), 'system'
FROM ccdb_stg.o_payments_stg p
LEFT JOIN ccdb_dummy.consumers c USING (consumer_num)
WHERE p.section_code = $1
RETURNING payment_id, receipt_id
)
INSERT INTO ccdb_dummy.payment_head_dtls(
payment_id, mbc_receipt_id, charge_head_code, amount, tariff_id,creation_dt,created_by)
SELECT i.payment_id,h.mbc_receipt_id,h.charge_head_code,h.amount,h.tariff_id,now(), 'system'
FROM ins1 i
JOIN ccdb_stg.o_payment_head_dtls_stg h ON h.mbc_receipt_id = i.receipt_id;
$func$;
应该与上面的 plpgsql 函数完全相同(除非翻译错误)。只是更简单、更快.
在 SO 上查找使用数据修改 CTE 的 INSERT 的更多示例。 https://stackoverflow.com/search?q=%5Bpostgres%5D%20%22data-modifying%20CTE%22%20insert