我正在将数据从表A复制到表B.在表A中,我有四列国家(EN,ES,RU,UK)。每个国家/地区的列是表B中的一个单独的行。此外,表B中的每一行都必须重复并接收下一个序列号。
表A - 我的光标
+---------+---------+---------+---------+---------+
| Company | EN | ES | RU | UK |
+---------+---------+---------+---------+---------+
| Intel | 123 345 | 453 343 | 444 101 | 110 232 |
+---------+---------+---------+---------+---------+
表B
+---------+---------+-----+
| Company | Country | SEQ |
+---------+---------+-----+
| Intel | 123 345 | 0 |
| Intel | 123 345 | 1 |
| Intel | 453 343 | 0 |
| Intel | 453 343 | 1 |
| INTEL | 444 101 | 0 |
| INTEL | 444 101 | 1 |
| INTEL | 110 232 | 0 |
| INTEL | 110 232 | 1 |
+---------+---------+-----+
在表A中,我有1,000,000行。
在表B中,我应该有1,000,000(行)x 4(国家)x 2(seq)= 8,000,000。
我准备了插入数据的程序。
BEGIN
OPEN my_cursor;
LOOP
EXIT WHEN my_cursor%notfound;
FETCH my_cursor BULK COLLECT INTO TAB LIMIT 500;
FOR y in 0..1 LOOP
FORALL x IN TAB.first..TAB.last
INSERT INTO table_B ("company","country","seq") VALUES (tab(x)."company", tab(x)."EN", y);
FORALL x IN TAB.first..TAB.last
INSERT INTO table_B ("company","country","seq") VALUES (tab(x)."company", tab(x)."ES", y);
FORALL x IN TAB.first..TAB.last
INSERT INTO table_B ("company","country","seq") VALUES (tab(x)."company", tab(x)."RU", y);
FORALL x IN TAB.first..TAB.last
INSERT INTO table_B ("company","country","seq") VALUES (tab(x)."company", tab(x)."UK", y);
END LOOP;
COMMIT;
END LOOP;
CLOSE my_cursor;
END;
如果表B中出现DML错误,我必须将数组(tab)中的变量值与DBMS_OUTPUT中的错误代码一起返回 例如:
DBMS_OUTPUT.PUT_LINE(tab(x)."company" || ' ' || tab(x)."UK" || SQLERRM);
是否可以处理此类错误?我该如何实施这样的解决方案?
答案 0 :(得分:0)
是的,您可以处理此类错误并继续使用SAVE EXCEPTIONS
与FORALL
进行所有插入,如下所示:
执行完所有语句后,PLSQL会引发ORA:24381
。
BEGIN
FORALL x IN TAB.first..TAB.last SAVE EXCEPTIONS
INSERT INTO table_B ("company","country","seq") VALUES (tab(x)."company", tab(x)."EN", y);
EXCEPTION
WHEN OTHERS THEN
IF sqlcode = -24381
FOR indx IN 1 .. SQL%BULK_EXCEPTIONS.COUNT
LOOP
DBMS_OUTPUT.put_line (
SQL%BULK_EXCEPTIONS (indx).ERROR_INDEX
|| ‘: ‘
|| SQL%BULK_EXCEPTIONS (indx).ERROR_CODE);
END LOOP;
else
raise;
end if;
END;
答案 1 :(得分:-1)
您可以使用FOR ALL ... SAVE EXCEPTIONS
指令来实现目标。
这将为您提供以下内容:
DECLARE
ln_error_count NUMBER;
ln_line_error NUMBER;
BEGIN
OPEN my_cursor;
LOOP
EXIT WHEN my_cursor%notfound;
FETCH my_cursor BULK COLLECT INTO TAB LIMIT 500;
FOR y in 0..1 LOOP
BEGIN
FORALL x IN TAB.first..TAB.last SAVE EXCEPTIONS
INSERT INTO table_B ("company","country","seq") VALUES (tab(x)."company", tab(x)."EN", y);
EXCEPTION
WHEN ex_dml_errors THEN
ln_error_count := SQL%BULK_EXCEPTIONS.count;
FOR i IN 1 .. ln_error_count LOOP
ln_line_error := SQL%BULK_EXCEPTIONS(i).error_index;
DBMS_OUTPUT.PUT_LINE(tab(ln_line_error)."company" || ' ' || tab(ln_line_error)."EN" || SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
END LOOP;
END;
BEGIN
FORALL x IN TAB.first..TAB.last SAVE EXCEPTIONS
INSERT INTO table_B ("company","country","seq") VALUES (tab(x)."company", tab(x)."ES", y);
EXCEPTION
WHEN ex_dml_errors THEN
ln_error_count := SQL%BULK_EXCEPTIONS.count;
FOR i IN 1 .. ln_error_count LOOP
ln_line_error := SQL%BULK_EXCEPTIONS(i).error_index;
DBMS_OUTPUT.PUT_LINE(tab(ln_line_error)."company" || ' ' || tab(ln_line_error)."ES" || SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
END LOOP;
END;
BEGIN
FORALL x IN TAB.first..TAB.last SAVE EXCEPTIONS
INSERT INTO table_B ("company","country","seq") VALUES (tab(x)."company", tab(x)."RU", y);
EXCEPTION
WHEN ex_dml_errors THEN
ln_error_count := SQL%BULK_EXCEPTIONS.count;
FOR i IN 1 .. ln_error_count LOOP
ln_line_error := SQL%BULK_EXCEPTIONS(i).error_index;
DBMS_OUTPUT.PUT_LINE(tab(ln_line_error)."company" || ' ' || tab(ln_line_error)."RU" || SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
END LOOP;
END;
BEGIN
FORALL x IN TAB.first..TAB.last SAVE EXCEPTIONS
INSERT INTO table_B ("company","country","seq") VALUES (tab(x)."company", tab(x)."UK", y);
EXCEPTION
WHEN ex_dml_errors THEN
ln_error_count := SQL%BULK_EXCEPTIONS.count;
FOR i IN 1 .. ln_error_count LOOP
ln_line_error := SQL%BULK_EXCEPTIONS(i).error_index;
DBMS_OUTPUT.PUT_LINE(tab(ln_line_error)."company" || ' ' || tab(ln_line_error)."UK" || SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
END LOOP;
END;
END LOOP;
COMMIT;
END LOOP;
CLOSE my_cursor;
END;