1

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

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

在我的远程数据库中,我创建了 col1 一个主键。因此,在插入时,如果存在重复键,则会引发错误,最终导致其余过程失败。我不想。我在考虑两种方法

  1. 编写一个 PLSQL 脚本,对于每个值,确定值是否已经存在。如果没有,则插入。
  2. 编写一个 PLSQL 脚本并插入并捕获重复键异常。例外将被忽略,它将继续插入(听起来不太好)。

您更喜欢哪种方法?我还能做些什么吗?

4

3 回答 3

2

我会使用 MERGE 语句和 WHEN NOT MATCHED THEN INSERT。

相同的合并也可以更新,但不必更新,只需将更新部分排除在外。

于 2013-03-28T19:30:15.907 回答
1

不同的数据库可以有重复的主键,但这并不意味着记录是重复的。每种情况下的实际数据可能不同。或者记录可能代表相同的现实世界事物但处于不同的状态,不知道,您没有提供足够的解释。

关键是,您需要更多分析为什么会存在重复记录,并且可能需要更复杂的方法来处理冲突。您是否需要获取所有记录(在这种情况下您需要合成密钥)?或者你只取一个实例(那么你如何决定优先级)?可能存在其他情况。

在任何情况下,MERGE 或 PL/SQL 循环都可能是一种过于粗糙的解决方案。

于 2013-03-29T00:53:59.193 回答
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;

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

于 2013-04-04T17:29:08.257 回答