如何根据表中的现有行将值插入表中

时间:2018-05-07 09:28:18

标签: sql oracle

我有一个表 inv_dtl ,其序列为主键。 我需要一个insert语句来按照以下要求插入值:

  1. 如果表中已存在该行(主键值除外),我需要插入值为“I”的最后一列( status_flag )的值。

  2. 如果它不存在,我需要插入带有 status_flag 列值'A'的值。

4 个答案:

答案 0 :(得分:3)

据我所知,您正在使用某种语言来处理数据库。

有两种方法:

  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)

答案 1 :(得分:1)

假设表" 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');

答案 2 :(得分:1)

从这个问题来看,似乎所有匹配的记录只有一行,其中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> 

答案 3 :(得分:0)

以下是您的解决方案的一步一步。退房可能对您有用。

创建功能

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