The code below is the answer from my question yesterday that has the ff results:
First run
Updated: 0
Inserted: 4
2nd run
Updated: 4
Inserted: 0
After deleting cid '1' and '3':
Updated: 2
Inserted: 2
DECLARE
ins NUMBER := 0;
upd NUMBER := 0;
CURSOR c1 IS
SELECT cid
FROM tbl_cust
WHERE cid
IN ('1','2','3','4');
BEGIN
FOR rec IN c1 LOOP
begin
INSERT INTO tbl2 (id_tbl2, name_tbl2)
VALUES(rec.cid, DECODE(rec.cid, '1', 'A',
'2', 'B',
'3', 'C',
'4', 'D'));
ins := ins + 1;
EXCEPTION WHEN DUP_VAL_ON_INDEX THEN
UPDATE tbl2 set name_tbl2 = DECODE(rec.cid, '1', 'A',
'2', 'B',
'3', 'C',
'4', 'D'));
WHERE cust_cust_code = rec.cid;
upd := upd + 1;
continue;
end;
END LOOP;
dbms_output.put_line('Updated: ' || upd);
dbms_output.put_line('Inserted: ' || ins);
END;
What I wanted now is to revise this code without using nested block. Maybe something like this:
DECLARE
ins NUMBER := 0;
upd NUMBER := 0;
CURSOR c1 IS
SELECT cid
FROM tbl_cust
WHERE cid
IN ('1','2','3','4');
--maybe declare something as 'holder of values' which are ducplicates and cannot be inserted then will be used on a condition or loop to update.
BEGIN
FOR rec IN c1 LOOP
INSERT INTO tbl2 (id_tbl2, name_tbl2)
VALUES(rec.cid, DECODE(rec.cid, '1', 'A',
'2', 'B',
'3', 'C',
'4', 'D'));
ins := ins + 1;
--maybe put some condition here to pass the values that are not insert to the 'holder of values'
END LOOP;
dbms_output.put_line('Updated: ' || upd);
dbms_output.put_line('Inserted: ' || ins);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
--maybe put a loop here to update values in the 'holder of values'
UPDATE tbl2 set name_tbl2 = DECODE('holder of values'.VALUE, '1', 'A',
'2', 'B',
'3', 'C',
'4', 'D')
WHERE cust_cust_code = 'holder of values'.VALUE;
upd := upd + 1;
dbms_output.put_line('Updated: ' || upd);
dbms_output.put_line('Inserted: ' || ins);
END;
答案 0 :(得分:1)
实际上,最好的方法是merge
,正如许多其他人所建议的那样。
(首先要提到的是@APC)
但是,如果你坚持你的逻辑,那么你应该使用某种集合。 (看看Working with Collections)。
尽管如此,你不能把异常处理放在循环之外它仍然应该在里面。
这可能是这样的:
DECLARE
ins NUMBER := 0;
upd NUMBER := 0;
CURSOR c1 IS
SELECT cid
FROM tbl_cust
WHERE cid
IN ('1','2','3','4');
--declare something as 'holder of values'
TYPE list_of_ids IS TABLE OF number;
duplicates list_of_ids:= list_of_ids ();
BEGIN
FOR rec IN c1 LOOP
begin
INSERT INTO tbl2 (id_tbl2, name_tbl2)
VALUES(rec.cid, DECODE(rec.cid, '1', 'A',
'2', 'B',
'3', 'C',
'4', 'D'));
ins := ins + sql%rowcount;
EXCEPTION WHEN DUP_VAL_ON_INDEX THEN
duplicates.EXTEND;
duplicates(duplicates.LAST):=rec.cid;
end;
--condition here to pass the values that are not insert to the 'holder of values'
END LOOP;
dbms_output.put_line('Updated: ' || upd);
dbms_output.put_line('Inserted: ' || ins);
--a loop here to update values in the 'holder of values'
FOR l_row IN 1 .. duplicates.COUNT
LOOP
UPDATE tbl2 set name_tbl2 = DECODE(duplicates (l_row), '1', 'A',
'2', 'B',
'3', 'C',
'4', 'D')
WHERE cust_cust_code := duplicates (l_row);
upd := upd + sql%rowcount;
DBMS_OUTPUT.put_line (duplicates (l_row));
END LOOP;
dbms_output.put_line('Updated: ' || upd);
dbms_output.put_line('Inserted: ' || ins);
END;