Как вставить значения в таблицу на основе существующих строк в таблице - PullRequest
0 голосов
/ 07 мая 2018

У меня есть таблица inv_dtl с последовательностью в качестве первичного ключа. Мне нужно оператор вставки для вставки значений в соответствии со следующими требованиями:

  1. Если строка уже существует в таблице (исключая значение первичного ключа), мне нужно вставить значения с последним столбцом ( status_flag ) со значением 'I'.

  2. Если его не существует, мне нужно вставить значения с status_flag значение столбца 'A'.

Ответы [ 4 ]

0 голосов
/ 07 мая 2018

Вот шаг за шагом, к вашему решению. проверка может быть полезна для вас.

Создание ФУНКЦИИ:

CREATE OR REPLACE FUNCTION inv_dtl_seq_fnc(p1 number)
 RETURN NUMBER
IS
  v_seq_val  NUMBER;
BEGIN
if p1 = 0 then
  EXECUTE IMMEDIATE 'select inv_dtl_seq.nextval from dual'
     INTO v_seq_val;
elsif p1=1 then
  EXECUTE IMMEDIATE 'select inv_dtl_seq.currval from dual'
     INTO v_seq_val;
end if;

  RETURN v_seq_val;
END inv_dtl_seq_fnc;

Фактический вариант использования:

create table inv_dtl(id number, status varchar2(200));
create sequence inv_dtl_seq
     start with 1
     increment by 1 
     nocache 
     nocycle;


insert into inv_dtl values(1,'A');
select * from inv_dtl;

ID  STATUS
1   A

insert into inv_dtl(id,status) 
  values (inv_dtl_seq_fnc(0),case when (select count(1) from inv_dtl where id = inv_dtl_seq_fnc(1)) > 0 then 'I' else 'A' end);

select * from inv_dtl;
ID  STATUS
1   A
1   I

insert into inv_dtl(id,status) 
  values (inv_dtl_seq_fnc(0),case when (select count(1) from inv_dtl where id = inv_dtl_seq_fnc(1)) > 0 then 'I' else 'A' end);

ID  STATUS
1   A
1   I
2   A
0 голосов
/ 07 мая 2018

Как я понимаю, вы используете какой-то язык для работы с базой данных.

Есть два способа:

  1. Сначала проверьте, существует ли запись: select 1 from inv_dtl where col1 = val1 and col2 = val2 etc. Затем вставьте новую запись с разными флагами. Какой флаг вы выбираете в исходном коде вашего языка.
  2. Использовать сложный SQL-оператор: insert into inv_dtl(col1, col2, etc.) values(val1, val2, etc., case (select 'X' from inv_dtl where col1 = val1 and col2 = val2, etc.) when 'X' then 'I' else 'A' end)
0 голосов
/ 07 мая 2018

Судя по этому вопросу, похоже, что для всех совпадающих записей может быть только одна строка, для которой status_flag будет иметь значение «A», при условии, что вы можете написать запрос, используя левое внешнее соединение для новых значений, а затем использовать инструкция case для определения значения status_code.

INSERT INTO inv_dtl
SELECT a.p_id,
       a.col1,
       a.col2,
       CASE WHEN b.status_flag IS NULL THEN 'A' ELSE 'I' END AS status_flag
  FROM (SELECT 1 p_id, -- new values goes here
               100 col1,
               'new 2' col2,
               'A' status_flag
          FROM dual) a
  LEFT OUTER JOIN (SELECT * FROM inv_dtl) b
    ON b.col1 = a.col1 -- all columns list goes here
   AND b.col2 = a.col2
   AND b.status_flag = 'A'; -- Status 'A' is fixed.

Тестирование кода:

SQL> create table inv_dtl(p_key number, col1 number, col2 varchar2(10), status_flag varchar2(1));
Table created

SQL> INSERT INTO inv_dtl
  2  SELECT a.p_id,
  3         a.col1,
  4         a.col2,
  5         CASE WHEN b.status_flag IS NULL THEN 'A' ELSE 'I' END AS status_flag
  6    FROM (SELECT 1 p_id,
  7                 100 col1,
  8                 'new' col2,
  9                 'A' status_flag
 10            FROM dual) a
 11    LEFT OUTER JOIN (SELECT * FROM inv_dtl) b
 12      ON b.col1 = a.col1
 13     AND b.col2 = a.col2
 14     AND b.status_flag = 'A';
1 row inserted

SQL> 
SQL> INSERT INTO inv_dtl
  2  SELECT a.p_id,
  3         a.col1,
  4         a.col2,
  5         CASE WHEN b.status_flag IS NULL THEN 'A' ELSE 'I' END AS status_flag
  6    FROM (SELECT 2 p_id,
  7                 100 col1,
  8                 'new' col2,
  9                 'A' status_flag
 10            FROM dual) a
 11    LEFT OUTER JOIN (SELECT * FROM inv_dtl) b
 12      ON b.col1 = a.col1
 13     AND b.col2 = a.col2
 14     AND b.status_flag = 'A';
1 row inserted

SQL> 
SQL> INSERT INTO inv_dtl
  2  SELECT a.p_id,
  3         a.col1,
  4         a.col2,
  5         CASE WHEN b.status_flag IS NULL THEN 'A' ELSE 'I' END AS status_flag
  6    FROM (SELECT 3 p_id,
  7                 100 col1,
  8                 'new' col2,
  9                 'A' status_flag
 10            FROM dual) a
 11    LEFT OUTER JOIN (SELECT * FROM inv_dtl) b
 12      ON b.col1 = a.col1
 13     AND b.col2 = a.col2
 14     AND b.status_flag = 'A';
1 row inserted

SQL> 
SQL> INSERT INTO inv_dtl
  2  SELECT a.p_id,
  3         a.col1,
  4         a.col2,
  5         CASE WHEN b.status_flag IS NULL THEN 'A' ELSE 'I' END AS status_flag
  6    FROM (SELECT 4 p_id,
  7                 200 col1,
  8                 'new 2' col2,
  9                 'A' status_flag
 10            FROM dual) a
 11    LEFT OUTER JOIN (SELECT * FROM inv_dtl) b
 12      ON b.col1 = a.col1
 13     AND b.col2 = a.col2
 14     AND b.status_flag = 'A';
1 row inserted

SQL> 
SQL> INSERT INTO inv_dtl
  2  SELECT a.p_id,
  3         a.col1,
  4         a.col2,
  5         CASE WHEN b.status_flag IS NULL THEN 'A' ELSE 'I' END AS status_flag
  6    FROM (SELECT 5 p_id,
  7                 200 col1,
  8                 'new 2' col2,
  9                 'A' status_flag
 10            FROM dual) a
 11    LEFT OUTER JOIN (SELECT * FROM inv_dtl) b
 12      ON b.col1 = a.col1
 13     AND b.col2 = a.col2
 14     AND b.status_flag = 'A';
1 row inserted

SQL> select * from inv_dtl;
     P_KEY       COL1 COL2       STATUS_FLAG
---------- ---------- ---------- -----------
         1        100 new        A
         2        100 new        I
         3        100 new        I
         4        200 new 2      A
         5        200 new 2      I

SQL> 
0 голосов
/ 07 мая 2018

Предполагая, что таблица "inv_dtl" содержит поля ("ID", "status_flag"). И последовательность с именем "inv_dtl_seq".

Сначала вы должны создать функцию, как показано ниже

CREATE OR REPLACE FUNCTION inv_dtl_seq_fnc
 RETURN NUMBER
IS
  v_seq_val  NUMBER;
BEGIN
  EXECUTE IMMEDIATE 'select inv_dtl_seq.nextval from dual'
     INTO v_seq_val;

  RETURN v_seq_val;
END inv_dtl_seq_fnc;

Теперь попробуйте приведенный ниже блок SQL, который будет вам полезен.

merge into inv_dtl i
using (select inv_dtl_seq_fnc new_id from dual) d
  on (i.id = d.new_id)
when matched then 
  update set status = 'I'
when not matched then
insert values(d.new_id,'A');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...