Your function, radically simplified:
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$;
Use the implicit cursor of a
FOR LOOP
instead of unwieldy explicit cursors coupled with redundant counts and loops. Much simpler and faster. Read the chapter "Looping Through Query Results" in the manual.LEFT JOIN
toccdb_dummy.consumers
in the firstSELECT
instead of running a separate select for every row.Also include
nextval('ccdb_stg.payments_seq') AS payment_no
in the firstSELECT
. Cheaper than lots of separate queries.
But that's far from perfect, yet. Consider a completely new approach with set-based operations instead of individual inserts in loops. Much cleaner and faster, yet. That's how modern RDBMS operate best.
One SQL statement with a data-modifying CTE
Wrapped into an SQL function to be a drop-in replacement.
Data-modifying CTEs require Postgres 9.1 or later.
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$;
Should do the same as the above plpgsql function exactly (barring errors in translation). Just much simpler and faster.
Find more examples for INSERTs using data-modifying CTEs here on SO.