Oracle 在列中插入数据以避免重复

Oracle 在列中插入数据以避免重复,oracle,plsql,oracle11g,Oracle,Plsql,Oracle11g,假设我有一个查询,它在连接多个表之后获取col1。我想在远程数据库上的表中插入col1的值,也就是说,我将使用dblink来实现这一点 现在,col1将从4-5个不同的数据库中获取。在db2中,从db1获取value1也有可能是b。如何避免重复 在我的远程数据库中,我创建了一个主键col1。所以,在插入时,若存在重复的密钥,则会抛出一个错误,最终导致进程的其余部分失败。我不想这样。我在想两种方法 为每个值编写一个PLSQL脚本,确定值是否已经存在。如果没有,则插入 编写PLSQL脚本,插入并捕获

假设我有一个查询,它在连接多个表之后获取col1。我想在远程数据库上的表中插入col1的值,也就是说,我将使用dblink来实现这一点

现在,col1将从4-5个不同的数据库中获取。在db2中,从db1获取value1也有可能是b。如何避免重复

在我的远程数据库中,我创建了一个主键col1。所以,在插入时,若存在重复的密钥,则会抛出一个错误,最终导致进程的其余部分失败。我不想这样。我在想两种方法

  • 为每个值编写一个PLSQL脚本,确定值是否已经存在。如果没有,则插入
  • 编写PLSQL脚本,插入并捕获重复密钥异常。例外情况是忽略,它将继续插入(听起来不太好)

  • 你喜欢哪种方法?还有什么我可以做的吗?

    我会使用MERGE语句,如果不匹配,则插入。


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

    我将使用MERGE语句,如果不匹配,则插入。


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

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

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


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

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

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


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

    首先,我建议您的目标数据库驱动所有这些插入,因为跨数据库链接插入/更新会产生一些锁定问题,并使事情进一步复杂化,特别是当多个数据库试图访问同一个表并执行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;
    

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

    首先,我建议您的目标数据库驱动所有这些插入,因为跨数据库链接插入/更新会产生一些锁定问题,并使事情进一步复杂化,特别是当多个数据库试图访问同一个表并执行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;
    

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

    4-5个不同的数据库是否都有自己的选择数据和远程插入过程。或者,您是在一条SQL语句中从4-5个数据库中进行选择,然后远程插入?或者,带表的远程数据库是否有一个
    INSERT…SELECT DISTINCT…FROMtable@remotedb1, table@remotedb2
    从所有远程数据库获取数据?每个数据库都有自己的脚本插入到一个公共数据库中。4-5个不同的数据库是否都有自己的过程来选择数据并远程插入。或者,您是在一条SQL语句中从4-5个数据库中进行选择,然后远程插入?或者,带表的远程数据库是否有一个
    INSERT…SELECT DISTINCT…FROMtable@remotedb1, table@remotedb2
    从所有远程数据库获取数据?每个数据库都有自己的脚本插入到一个公共数据库中。merge语句可以用作大容量合并吗?我使用insert语句的原因是
    FORALL
    bulk insert。您可以声明对象类型,然后声明该类型的表,然后将集合转换为“表(您的集合)”,而不是使用
    FORALL