Вставить выберите продолжить с ошибкой

У меня есть несколько сценариев SQL, которые используют

INSERT INTO secondtable 
  (field, field1)
SELECT field, field2 
  FROM table;

Я использую oracle 9.x и sqldevelopper.

Когда я запускаю их, при некоторой вставке я получаю ошибки внешнего ключа. И поэтому они не вставили набор, кто работает.

Можно ли сказать оракулу, чтобы он продолжал то же самое при появлении ошибки и, если возможно, отображать или регистрировать ошибку?

2 ответа

Решение

Вы не можете продолжить неудачную вставку на основе набора в ORacle 9. Вы должны либо сделать оператор отказоустойчивым, либо принять, что он будет откатан.

Опции:

  1. Если такие ошибки редки, попробуйте действие на основе набора и добавьте обработчик исключений, который выполняет решение на основе строк при возникновении ошибки и отображает ошибки (или сохраняет их где-то для дальнейшей обработки) при возникновении ошибок. Да, это дублирует усилия, но в большинстве случаев это будет наиболее эффективная операция, и при возникновении ошибок она будет обрабатываться по вашему усмотрению.

  2. Если это обычное явление, смирись с этим и переключись на решение на основе строк, как указано выше. Оптимизируйте как можно лучше и надеемся, что когда-нибудь вы сможете воспользоваться #3)

  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 );
Другие вопросы по тегам