在列中插入数据,避免重复

时间:2013-03-28 17:13:02

标签: oracle plsql oracle11g

假设我有一个查询,它在连接多个表后获取col1。我想在远程数据库上的表中插入该col1的值,即我将使用dblink来执行此操作。

现在col1将从4-5个不同的db中获取。有可能db2中的value1从db2中获取b。我怎样才能避免重复?

在我的远程数据库中,我已经为col1创建了一个主键。因此,在插入时,如果存在重复键,则会抛出错误,最终结果会导致进程无效。我不想这样做。我对两种方法感到兴奋

  1. 编写PLSQL脚本,对于每个值,确定值是否已存在。如果没有则插入。
  2. 编写PLSQL脚本并插入并捕获重复键异常。异常将被忽略,它将继续插入(听起来不太好)。
  3. 您更喜欢哪种方法?还有什么我可以做的吗?

2 个答案:

答案 0 :(得分:2)

我会使用MERGE语句,而不是匹配然后插入。

同样的合并也可以更新但不必更新,只需将更新部分保留下来。

答案 1 :(得分:1)

首先,我建议您的目标数据库驱动所有这些插入,因为跨数据库链接插入/更新可能会产生一些锁定问题,并进一步使事情复杂化,特别是对于尝试在同一个表上访问和执行DML的多个数据库。但是,如果不可能,以下解决方案将起作用。

我会通过在每个目标表上包含一个表查找来修复主键问题。

INSERT INTO customer@dblink.oracle.com cust
(emp_name,
 emp_id)
VALUES
(SELECT 
    cust.employee_name, 
    cust.employee_id --primary_key
FROM
    source_table st
WHERE NOT EXISTS
  (SELECT 1 
   FROM customer@dblink.oracle.com cust
   WHERE cust.employee_id = st.emp_id));

同样,我不推荐跨数据库链接的DML事务,除非绝对必要,因为你有时会有奇怪的锁定行为。

PL / SQL过程或匿名PL / SQL块可用于创建批量处理解决方案,如下所示:

CREATE OR REPLACE PROCEDURE send_unique_data
AS
  TYPE tab_cust IS TABLE OF customer@dblink.oracle.com%ROWTYPE
     INDEX BY PLS_INTEGER;
  t_records   tab_cust;

BEGIN
    SELECT 
      cust.employee_name, 
      cust.employee_id --primary_key
    BULK COLLECT
    INTO t_records
    FROM source_table;

    FORALL i IN t_records.FIRST...t_records.LAST SAVE EXCEPTIONS
        INSERT INTO customer@dblink.oracle.com
        VALUES t_records(i);
END send_unique_data;

如果要对引发异常的记录(例如unique_constraint违规)执行任何操作,也可以调用系统SQL%BULKEXCEPTIONS集合。请注意,如果尝试插入大量重复数据,此解决方案将导致目标表出现性能问题。