Проблема в том, что ваш первый курсор возвращает две строки, каждая из которых имеет значение 11 для END_ORD_NO
. Второй курсор выполняется для каждой из двух строк, возвращаемых первым курсором, и каждое выполнение второго курсора возвращает две строки, значения из которых должным образом вставляются в FINAL_TAB
.
Чтобы исправить это, вы должны объединить два курсора в один курсор:
SELECT a.order_no,
a.order_item,
a.header_id,
b.line_id
FROM tab1 a, tab2 b
WHERE a.header_id = b.header_id AND
a.order_no IN (SELECT b.attribute1
FROM tab1 a, tab2 b
WHERE a.header_id = b.header_id AND
a.order_no = 1)
, который уменьшает ваш кодовый блок до
DECLARE
CURSOR cc IS
SELECT a.order_no,
a.order_item,
a.header_id,
b.line_id
FROM tab1 a, tab2 b
WHERE a.header_id = b.header_id AND
a.order_no IN (SELECT b.attribute1
FROM tab1 a, tab2 b
WHERE a.header_id = b.header_id AND
a.order_no = 1);
BEGIN
FOR rec IN cc LOOP
INSERT INTO final_tab (order_no, order_item, line_id)
VALUES (rec.order_no, rec.order_item, rec.line_id);
END LOOP;
COMMIT;
END;
Это не только обеспечит требуемые результаты, но также уменьшит вероятность ошибок за счет упрощения кода и сократит время выполнения за счет исключения вложенных циклов.
Однако даже это можно еще более упростить до
INSERT INTO final_tab (order_no, order_item, line_id)
SELECT a.order_no,
a.order_item,
b.line_id
FROM tab1 a, tab2 b
WHERE a.header_id = b.header_id AND
a.order_no IN (SELECT b.attribute1
FROM tab1 a, tab2 b
WHERE a.header_id = b.header_id AND
a.order_no = 1)
Это имеет то преимущество, что выполняет всю задачу, не требуя использования какого-либо цикла, и является более быстрым, поскольку вся операция выполняется базой данных без необходимости замедления взаимодействия с внешней процедурой.
dbfiddle здесь
Удачи.
EDIT
Если вы должны использовать оба курсора, возможно, вы могли бы использовать оператор MERGE следующим образом:
DECLARE
CURSOR c1
IS
SELECT a.order_no,
a.order_item,
b.attribute1 end_ord_no,
a.header_id,
b.line_id
FROM tab1 a, tab2 b
WHERE a.header_id = b.header_id AND a.order_no = 1;
CURSOR c2 (i_ord_no NUMBER)
IS
SELECT a.order_no,
a.order_item,
a.header_id,
b.line_id
FROM tab1 a, tab2 b
WHERE a.header_id = b.header_id AND a.order_no = i_ord_no;
BEGIN
FOR c1_rec IN c1 LOOP
FOR c2_rec IN c2 (c1_rec.end_ord_no) LOOP
MERGE INTO FINAL_TAB ft
USING (SELECT c2_rec.order_no AS ORDER_NO,
c2_rec.order_item AS ORDER_ITEM,
c2_rec.line_id AS LINE_ID
FROM DUAL) d
ON (ft.ORDER_NO = d.ORDER_NO AND
ft.ORDER_ITEM = d.ORDER_ITEM AND
ft.LINE_ID = d.LINE_ID)
WHEN NOT MATCHED THEN
INSERT (order_no, order_item, line_id)
VALUES (d.order_no, d.order_item, d.line_id);
END LOOP; -- c2_rec
END LOOP; -- c1_rec
COMMIT;
END;