Вставить выберите продолжить с ошибкой - PullRequest
1 голос
/ 09 февраля 2011

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

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

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

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

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

Ответы [ 2 ]

5 голосов
/ 09 февраля 2011

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

Опции:

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

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

  3. Обновите систему до Oracle 10 и воспользуйтесь Ведение журнала ошибок DML

3 голосов
/ 09 февраля 2011

Нет в 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 );
...