批量INSERT或UPDATE忽略Oracle

时间:2016-09-13 17:31:55

标签: sql oracle plsql

对于批量加载导入的数据,我进行了一些处理,并将该处理的结果存储在临时表中。然后,我可以使用分阶段数据将更改应用于其他表。

当导入的数据正确时,这非常有效,但有时可能包含错误,例如对未使用的外键的引用或主键的重复

我想实现类似下面的示例(当数据没有错误时有效),但而不是失败整个操作,我想记录冲突行并继续处理


实施例

假设我有一个items表和一个items_operations临时表。然后,在填充items_operations之后,我可以......

制作新商品

INSERT INTO items (id, name, manufacturer_id, price)
SELECT
  item_id,
  item_name,
  item_manufacturer_id
  item_price
FROM items_operations
WHERE operation = 'creation'

(如果id存在重复的manufactuer_id或不存在的FK,则可能会失败


更新现有项目

UPDATE items t1
SET (name, manufacturer_id, price) =
    (SELECT
        t2.item_name,
        t2.item_manufacturer_id,
        t2.item_price
    FROM items_operations t2
    WHERE t1.id = t2.item_id
        AND t2.operation = 'modification')
WHERE EXISTS (
SELECT 1
FROM items_operations t2
WHERE t1.id = t2.item_id
    AND t2.operation = 'modification')

(对于manufacturer_id

的未实现FK,这将失败


补充说明

  • 由于 SQL 操作必须是原子的,我认为我需要的可能需要使用 PL / SQL ,但我不太清楚什么我应该遵循哪种方法。
  • 另外,知道我的items表真的很大(约300MM记录)可能很重要,因此应该避免不必要的连接。
  • 最后,有时items_operations包含对未存在项目的更新(id上没有匹配items的{​​{1}})。这不会失败,但如果我能够记录那些不匹配的项目,那将是理想的。

1 个答案:

答案 0 :(得分:2)

听起来你想使用DML error logging

创建错误表(每个要加载的表一次)

begin
  dbms_errlog.create_error_log( dml_table_name => 'ITEMS' );
end;
/

然后您可以使用LOG ERRORS INTO子句

INSERT INTO items (id, name, manufacturer_id, price)
   SELECT
      item_id,
      item_name,
      item_manufacturer_id
      item_price
 FROM items_operations
WHERE operation = 'creation'
  LOG ERRORS INTO err$_items
    REJECT LIMIT UNLIMITED;

然后,您可以查询err$_items以查看引发的错误。

对于非失败的事物(即item_operationsitems中没有匹配行的项目),您需要运行查询才能找到它们。接下来,我将定义一个外键约束,阻止您在不存在的项上记录操作。