Переход назад и вперед между SQL и PLSQL дает огромные накладные расходы. В вашем случае вы выполняете запрос, а затем выполняете новые запросы для каждой записи, найденной в основном запросе. Это замедляет процесс из-за всех этих переключений контекста между SQL и PLSQL и из-за того, что отдельные запросы сложнее оптимизировать. Напишите один большой запрос. Оптимизатор может сделать всю свою магию, и у вас есть только один переключатель контекста.
Выполнить следующий запрос: каждая возвращаемая строка является ошибкой. Вам нужно только прочитать sourceCount и productCount, чтобы увидеть, какая из них является проблемой (или обе).
Чтобы вставить ошибки:
insert into tbl_errors (rec_id, e_id, desc)
select
s_id,
case
when sourceCount <> 1 then 1
when productCount <> 1 then 2
when ...
end as e_id,
case
when sourceCount <> 1 then 'source_id'
when productCount <> 1 then 'product_id'
when ...
end as reason
from
(
SELECT
MAX(t.s_id) as s_id,
t.sdate,t.stype,t.snumber,t.code,
SUM(t.amount) as amount,
(SELECT count(*)
FROM mapping m, source d
WHERE
TO_NUMBER(m.stage)=rec.snumber AND
m.month=EXTRACT(MONTH FROM rec.sdate) AND
m.year=EXTRACT(YEAR FROM rec.sdate) AND m.desc=d.source_desc AND
m.month=d.month AND m.year=d.year AND m.name='SOURCE') as sourceCount,
(SELECT count(*)
FROM mapping m, product p
WHERE
m.stage=rec.code AND
m.month=EXTRACT(MONTH FROM rec.sdate) AND
m.year=EXTRACT(YEAR FROM rec.sdate) AND
m.desc=p.product_name AND m.month=p.month AND
m.year=p.year AND m.name='PRODUCT') as productCount,
/* other checks */
FROM
stable t
WHERE
t.sdate=p_date AND t.stype=p_type
AND t.snumber=p_num
GROUP BY
t.sdate, t.snumber, t.stype
) x
having
sourceCount <> 1 or productCount <> 1 or /* other checks */
Чтобы вставить записи, которые в порядке. Используйте тот же запрос для проверок, но добавьте дополнительные подзапросы, чтобы получить правильный идентификатор продукта и идентификатор источника.
insert into tbl_destination(sdate,source_id,product_id,amount, ...)
select
sdate,
source_id,
product_id,
amount,
...
from
(
SELECT
MAX(t.s_id) as s_id,
t.sdate,t.stype,t.snumber,t.code,
SUM(t.amount) as amount,
(SELECT count(*)
FROM mapping m, source d
WHERE
TO_NUMBER(m.stage)=rec.snumber AND
m.month=EXTRACT(MONTH FROM rec.sdate) AND
m.year=EXTRACT(YEAR FROM rec.sdate) AND m.desc=d.source_desc AND
m.month=d.month AND m.year=d.year AND m.name='SOURCE') as sourceCount,
(SELECT min(source_id)
FROM mapping m, source d
WHERE
TO_NUMBER(m.stage)=rec.snumber AND
m.month=EXTRACT(MONTH FROM rec.sdate) AND
m.year=EXTRACT(YEAR FROM rec.sdate) AND m.desc=d.source_desc AND
m.month=d.month AND m.year=d.year AND m.name='SOURCE') as source_id,
(SELECT count(*)
FROM mapping m, product p
WHERE
m.stage=rec.code AND
m.month=EXTRACT(MONTH FROM rec.sdate) AND
m.year=EXTRACT(YEAR FROM rec.sdate) AND
m.desc=p.product_name AND m.month=p.month AND
m.year=p.year AND m.name='PRODUCT') as productCount,
(SELECT min(product_id)
FROM mapping m, product p
WHERE
m.stage=rec.code AND
m.month=EXTRACT(MONTH FROM rec.sdate) AND
m.year=EXTRACT(YEAR FROM rec.sdate) AND
m.desc=p.product_name AND m.month=p.month AND
m.year=p.year AND m.name='PRODUCT') as product_id,
/* other checks */
FROM
stable t
WHERE
t.sdate=p_date AND t.stype=p_type
AND t.snumber=p_num
GROUP BY
t.sdate, t.snumber, t.stype
) x
having
sourceCount = 1 and productCount = 1 and /* other checks */