Oracle SQL插入(如果不存在)

时间:2019-02-19 16:55:48

标签: sql oracle select insert insert-select

我有表foo和PK int idvarchar state

table foo:
- int id
- varchar state
- int code1
- int code2

如果记录不存在,我想执行sql插入操作。

要完成插入语句,我必须使用插入选择来检索一些信息。

在输入中,我有:

id = 1, state = 'A'

在插入中,我必须用插入选择检索到的值填充其他字段。

code1 and code2 where id = 1 (they are always the same for id = x)

通常我必须这样做:

1-使用where id=1 and state=1进行选择,如果不存在,则必须执行sql插入

2-如果记录不存在,则检索字段code1 and code2 when id=1

的值

3-插入

是否可以在一个查询中全部完成?

select * from foo where id=1 and state = 'A'

如果尚不存在:

select code1,code2 from foo where id=1; #1,2
insert into foo(id, state, code1, code2) values (1,'A', 1, 2);

是否可以在一个查询中合并?

谢谢

4 个答案:

答案 0 :(得分:0)

您可以使用insert . . . select

insert into foo (id, some)
    select 1, 'text'
    from dual
    where not exists (select 1 from foo where id = 1);

答案 1 :(得分:0)

为此,您可以使用* magical Oracle提示IGNORE_ROW_ON_DUPKEY_INDEX。提示无提示地跳过重复的插入行-通常会导致`ORA-00001:违反唯一约束(...)。

我假设设置了以下表格:

create table foo
(id number not null,
 status varchar2(1) not NULL,
 code1 varchar2(10),
 code2 varchar2(10));

alter table foo add (primary key (id, status)); 

insert into foo (id,status, code1,code2) values(1,'a','xxx', 'xxx');
insert into foo (id,status, code1,code2) values(1,'b','xxx', 'xxx');

insert into foo (id,status, code1,code2) values(2,'b','yyy', 'yyy');
commit;

因此,现在您要忽略状态为1的记录中的2来使用键code进行插入,并使用键'b'进行插入

这应该使您知道如何进行:

insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX (foo (id, status)) */ into foo (id,status, code1,code2) 
values( 1, 'a', 
(select code1 from foo where id = 1 and status = 'b'),
(select code2 from foo where id = 1 and status = 'b'));

0 rows created.

insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX (foo (id, status)) */ into foo (id,status, code1,code2) 
values( 2, 'a', 
(select code1 from foo where id = 2 and status = 'b'),
(select code2 from foo where id = 2 and status = 'b'));

1 rows created.

根据需要调整子查询以获取code1code2-您可以使用max(code1)并忽略status

使用绑定变量在查询中传递id(三次)。

答案 2 :(得分:0)

在表中,id是主键。因此,如果您尝试插入具有现有id的行,则oracle将引发错误。 您可以根据需要处理该错误。

但是,如果您“确实”要在插入之前进行检查,则可以尝试使用PL / SQL块。

PL / SQL

declare
  _id INTEGER
begin
  SELECT id into _id from foo;
exception
  when NO_DATA_FOUND then
    insert into foo(id,some) values (1,'text');
end;
/

注意:请确保在结尾加上/。这将运行您的PL / SQL块。

基本上,此块尝试选择具有给定id的行。如果存在,则只需正常结束该块。如果没有返回任何行,则这是该块的“例外”,您可以通过插入所需的内容来“处理”它。

另一种方式

begin
  insert into foo(id,some) values (1,'text');
exception
  when DUP_VAL_ON_INDEX then
    DBMS_OUTPUT.PUT_LINE('Already exists');
end;
/

注意::如果要查看PL / SQL块的任何输出,则可能需要执行 set serveroutput on; 在运行任何PL / SQL块之前。

希望这会有所帮助。

答案 3 :(得分:0)

在Oracle中的单个语句中执行此操作的方法是use the MERGE statement。对于您而言,您可以执行以下操作:

MERGE INTO FOO
  USING (SELECT f.ID,
                'A' AS STATE,
                f.CODE1,
                f.CODE2
           FROM FOO f
           WHERE f.ID = 1) d
    ON (d.ID = FOO.ID AND
        d.STATE = FOO.STATE)
  WHEN NOT MATCHED THEN INSERT
    (ID, STATE, CODE1, CODE2)
  VALUES
    (d.ID, d.STATE, d.CODE1, d.CODE2)

好运。