【问题标题】:plsql: inserting Multiple rows from select and ignore duplicatesplsql:从选择中插入多行并忽略重复项
【发布时间】:2014-12-26 14:25:40
【问题描述】:

我正在使用带有 TOAD 的 oracle 10g。 我需要使用 INSERT FROM SELECT 插入 lacs 记录。

BEGIN    
    INSERT INTO MYTABLE(C1,C2,C3)  
    SELECT C1,C2,C3 FROM MYTABLE2 WHERE C1>100;
EXCEPTION    
         WHEN DUP_VAL_ON_INDEX  THEN NULL;    
COMMIT;    
END;

这里,我面临的问题是,如果这个选择查询返回的行已经存在于 MYTABLE 中,那么所有事务都将被回滚。

有没有办法插入所有不存在的行,忽略重复的行并继续插入不存在的行,然后提交事务?

【问题讨论】:

  • 只需选择不同的 c1,c2,c3 ... where not exists (select 1 from mytable mt where mt.c1 = mytable.c1 and mt.c2 = mytable.c2 and mt.c3 = mytable.c3)
  • 嗨,迈克,选择查询从多个表中获取列。三列来自三个不同的表。
  • 你在编辑方面打败了我。您可能也可以进行合并,但正如您所见,有很多方法可以做到这一点。不匹配时使用 mytable2 m2 在 (m1.c1 = m2.c1 and m1.c2 = m2.c2 and m1.c3 = m2.c3) 上合并到 mytable m1,然后插入值 (m2.c1, m2.c2, m2. c3);

标签: oracle plsql


【解决方案1】:

使用独特的关键字

开始
插入 MYTABLE(C1,C2,C3)
从 MYTABLE2 中选择不同的 C1、C2、C3,其中 C1>100; 例外
当 DUP_VAL_ON_INDEX 为空时;
提交;
结束;

【讨论】:

  • 您好 Sandeep,选择查询从多个表中获取列。三列来自三个不同的表
  • 您好 User1583751,即使 select 查询从多个表中获取记录,distinct 关键字也会删除 C1、C2、C3 的所有重复条目,然后将记录插入到 MYTABLE 中
  • distinct 在使用多个表时失败。 Select 可能会给我来自 table2 的不同记录,但是在插入 table1 时,它不会识别 table1 中的不同记录。 select 和 distinct 位于 x 表中,而插入位于 y 表中。 :)
  • 您可以按照 Mike 的建议使用 Merge 语句,能否请您在此处粘贴您正在使用的确切 SQL 查询。
【解决方案2】:

您可以首先避免这些行,而不是尝试处理异常,例如,通过使用 minus 运算符:

INSERT INTO mytable (c1, c2, c3)  
SELECT c1, c2, c3 
FROM   mytable2 
WHERE  c1 > 100;
MINUS
SELECT c1, c2, c3
FROM   mytable
WHERE  c1 > 100 -- not necessary, but should improve performance

【讨论】:

  • 嗨 Mureinik,我需要知道我在异常部分跳过了哪些行。然后继续其他记录。但我的问题是,一旦引发异常,整个交易就会被抛售。
【解决方案3】:

有很多方法可以做到这一点。首先,你可以试试这样:

insert into mytable(c1, c2, c3)
select distinct c1, c2, c3 from mytable2 where c1 > 100
minus
select c1, c2, c3 from mytable;

否则,你可以使用类似的东西

insert into mytable(c1, c2, c3)
select c1, c2, c3 from mytable2 where c1 > 100
log errors into myerrtable reject limit unlimited;

等等……

有关错误记录的更多详细信息。自 10g 第 2 版以来引入的功能。

SQL> create table garbage(id integer);

Table created

SQL> insert into garbage select rownum from dual connect by level <= 10;

10 rows inserted

SQL> insert into garbage values (3);

1 row inserted

SQL> insert into garbage values (5);

1 row inserted

SQL> create table uniq(id integer not null primary key);

Table created

SQL> insert into uniq select * from garbage;

ORA-00001: unique constraint (TEST.SYS_C0010568) violated

SQL> select count(*) from uniq;

  COUNT(*)
----------
         0

SQL> exec dbms_errlog.create_error_log('uniq', 'uniq_err');

PL/SQL procedure successfully completed

SQL> insert into uniq select * from garbage
  2  log errors into uniq_err reject limit unlimited;

10 rows inserted

SQL> select * from uniq;

                                     ID
---------------------------------------
                                      1
                                      2
                                      3
                                      4
                                      5
                                      6
                                      7
                                      8
                                      9
                                     10

10 rows selected

SQL> select ora_err_mesg$, id from uniq_err;

ORA_ERR_MESG$                                                          ID
---------------------------------------------------------------------- --
ORA-00001: unique constraint (TEST.SYS_C0010568) violated              3
ORA-00001: unique constraint (TEST.SYS_C0010568) violated              5

【讨论】:

  • 我收到您的最后一行错误“将错误记录到 myerrtable 拒绝限制无限制;” [错误] 执行 (49: 5):ORA-06550:第 13 行,第 5 列:PLS-00103:在预期以下情况之一时遇到符号“错误”::=。 (@%;
【解决方案4】:

我以为我会回答这个问题,但这实际上取决于您要达到的目标。

您可以使用以下方法检查数据是否已在 table2 中:

INSERT INTO mytable2 (c1, c2, c3) 
SELECT DISTINCT c1,c2,c3 FROM mytable t1
WHERE c1 > 100 
AND NOT EXISTS 
(select 1 from mytable2 t2 where t2.c1 = t1.c1 and t2.c2 = t1.c2 and t2.c3 = t1.c3);

或者你可以使用这样的合并:

MERGE INTO mytable2 m2
USING (SELECT DISTINCT c1, c2, c3 FROM mytable) m1 
ON (m1.c1 = m2.c1 and m1.c2 = m2.c2 and m1.c3 = m2.c3) 
WHEN NOT MATCHED THEN INSERT (c1, c2, c3)  VALUES (m1.c1, m1.c2, m1.c3)
where m1.c1 > 100;

在这两个示例中,您只会将唯一行插入到 mytable2 中

【讨论】:

    猜你喜欢
    • 2014-02-19
    • 2020-05-31
    • 1970-01-01
    • 2017-06-19
    • 2021-07-29
    • 2020-05-19
    • 1970-01-01
    • 1970-01-01
    • 2012-11-27
    相关资源
    最近更新 更多