Вставить выберите продолжить с ошибкой
У меня есть несколько сценариев SQL, которые используют
INSERT INTO secondtable
(field, field1)
SELECT field, field2
FROM table;
Я использую oracle 9.x и sqldevelopper.
Когда я запускаю их, при некоторой вставке я получаю ошибки внешнего ключа. И поэтому они не вставили набор, кто работает.
Можно ли сказать оракулу, чтобы он продолжал то же самое при появлении ошибки и, если возможно, отображать или регистрировать ошибку?
2 ответа
Вы не можете продолжить неудачную вставку на основе набора в ORacle 9. Вы должны либо сделать оператор отказоустойчивым, либо принять, что он будет откатан.
Опции:
Если такие ошибки редки, попробуйте действие на основе набора и добавьте обработчик исключений, который выполняет решение на основе строк при возникновении ошибки и отображает ошибки (или сохраняет их где-то для дальнейшей обработки) при возникновении ошибок. Да, это дублирует усилия, но в большинстве случаев это будет наиболее эффективная операция, и при возникновении ошибок она будет обрабатываться по вашему усмотрению.
Если это обычное явление, смирись с этим и переключись на решение на основе строк, как указано выше. Оптимизируйте как можно лучше и надеемся, что когда-нибудь вы сможете воспользоваться #3)
Обновитесь до Oracle 10 и воспользуйтесь журналом ошибок DML
Нет в Oracle 9i, нет. В 10.2 было введено ведение журнала ошибок DML, и это именно то, что вам нужно.
В более ранних версиях наиболее распространенным подходом было бы делать PL/SQL, т.е.
BEGIN
FOR src IN (SELECT field1, field2
FROM source_table)
LOOP
BEGIN
INSERT INTO destination_table( field1, field2 )
VALUES( src.field1, src.field2 );
EXCEPTION
WHEN dup_val_on_index
THEN
<<log the foreign key error>>
END;
END LOOP;
END;
Вы также можете использовать SQL для разделения строк, которые нарушают внешний ключ, т.е.
INSERT INTO error_table( field1, field2 )
SELECT field1, field2
FROM source_table
WHERE NOT EXISTS(
SELECT 1
FROM parent_table
WHERE parent_table.field1 = source_table.field1 );
INSERT INTO destination_table( field1, field2 )
SELECT field1, field2
FROM source_table
WHERE EXISTS(
SELECT 1
FROM parent_table
WHERE parent_table.field1 = source_table.field1 );