plsql:从选择中插入多行并忽略重复项
Posted
技术标签:
【中文标题】plsql:从选择中插入多行并忽略重复项【英文标题】:plsql: inserting Multiple rows from select and ignore duplicates 【发布时间】: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); 【参考方案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 中
【讨论】:
以上是关于plsql:从选择中插入多行并忽略重复项的主要内容,如果未能解决你的问题,请参考以下文章