Oracle SQL вставить, если не существует - PullRequest
0 голосов
/ 19 февраля 2019

У меня есть таблица foo с PK int id, varchar 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 голосов
/ 19 февраля 2019

Способ сделать это с помощью одного оператора в Oracle - использовать оператор MERGE .В вашем случае вы бы сделали что-то вроде:

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)

Удачи.

0 голосов
/ 19 февраля 2019

Вы можете использовать * магический подсказку Оракула 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 s из записи со статусом '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.

Настройте подзапрос, чтобы получить code1 и code2 по мере необходимости - вы можете использовать max(code1) и игнорировать status.

Использовать переменную связывания для передачи id (три раза) в запросе.

0 голосов
/ 19 февраля 2019

В вашей таблице id является первичным ключом.Так что oracle выдаст ошибку, если вы попытаетесь вставить строку с существующим id.Вы можете обработать эту ошибку по своему усмотрению.

Но если вы действительно хотите проверить перед вставкой, вы можете попробовать 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.

Надеюсь, это поможет.

0 голосов
/ 19 февраля 2019

Вы можете использовать insert . . . select:

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