2009-06-30 1 views
3

Я работаю над переносом данных из старой системы в наше новое приложение (работает на базе Oracle Database 10gR2). В рамках миграции я работаю над скриптом, который вставляет данные в таблицы, которые используются приложением.Продолжающиеся вставки в Oracle при возникновении исключения

Число строк данных, которые импортируются, составляет тысячи, а исходные данные не являются чистыми (неожиданные значения нулей в столбцах NOT NULL и т. Д.). Поэтому, вставляя данные через скрипты, всякий раз, когда возникает такое исключение, скрипт заканчивается внезапно, и вся транзакция откатывается назад.

Есть ли способ, по которому я могу продолжать вставлять данные, для которых строки чисты? Использование NVL() или COALESCE() не является вариантом, так как я хотел бы регистрировать строки, вызывающие ошибки, чтобы данные могли быть исправлены для следующего прохода.

EDIT: В моей текущей процедуре есть обработчик исключений, я регистрирую первую строку, которая вызывает ошибку. Было бы возможно, чтобы вставки продолжались без прерывания, потому что прямо сейчас при исключении с первой обработкой процедура завершает выполнение.

ответ

5

Используя PLSQL, вы можете выполнять каждую вставку в своей собственной транзакции (COMMIT после каждого) и регистрировать или игнорировать ошибки с обработчиком исключений, который продолжает работать.

+0

обработчик исключений улавливает первую ошибку, а затем выходит из процедуры. Как я могу удержать его от выхода? – Sathya

+1

@ Арнеша правая - вставьте вставку внутри собственного блока: BEGIN insert ... EXCEPTION handle_exception END; – DCookie

+0

Спасибо, внедрил это и многое поможет. – Sathya

0

Если вы используете sqlldr, вы можете указать, чтобы продолжить загрузку данных, и все «плохие» данные будут пропущены и занесены в отдельный файл.

4

Попробуйте это:

for r_row in c_legacy_data loop 
    begin 
    insert into some_table(a, b, c, ...) 
    values (r_row.a, r_row.b, r_row.c, ...); 
    exception 
    when others then 
     null; /* or some extra logging */ 
    end; 
end loop; 
1
DECLARE 
    cursor; 
BEGIN 
    loop for each row in cursor 
     BEGIN -- subBlock begins 
     SAVEPOINT startTransaction; -- mark a savepoint 
-- do whatever you have do here 
     COMMIT;   
     EXCEPTION 
     ROLLBACK TO startTransaction; -- undo changes 
     END; -- subBlock ends 
    end loop; 
END; 
9

Если объемы данных были выше, строка за строкой обработки в PL/SQL, вероятно, будет слишком медленным. В этих условиях, вы можете использовать DML протоколирование ошибок, описанного here

CREATE TABLE raises (emp_id NUMBER, sal NUMBER 
    CONSTRAINT check_sal CHECK(sal > 8000)); 

EXECUTE DBMS_ERRLOG.CREATE_ERROR_LOG('raises', 'errlog'); 

INSERT INTO raises 
    SELECT employee_id, salary*1.1 FROM employees 
    WHERE commission_pct > .2 
    LOG ERRORS INTO errlog ('my_bad') REJECT LIMIT 10; 

SELECT ORA_ERR_MESG$, ORA_ERR_TAG$, emp_id, sal FROM errlog; 

ORA_ERR_MESG$    ORA_ERR_TAG$   EMP_ID SAL 
--------------------------- -------------------- ------ ------- 
ORA-02290: check constraint my_bad    161 7700 
(HR.SYS_C004266) violated 
+0

Просто прочитайте ссылку, которую вы предоставили, проверка DML имеет ограничение на невозможность захвата и, следовательно, сбой при уникальном нарушении ограничений, и я столкнулся с такими ошибками. В любом случае, я не знал об этом и, безусловно, буду полезен в других областях конверсии, над которыми я работаю. Благодарю. – Sathya