繁体   English   中英

如果 id 存在于另一个表中,则有条件地插入到另一个表中,否则插入到 oracle 中的两个表中

[英]Conditionally insert into another table if id exists in another table else insert into both both tables in oracle

如果表A 中存在客户 ID,则在表 B插入订单。 如果A 表中没有客户 ID,则在 A中插入客户 ID,然后在B表中订购。 我一直在尝试通过if/else 和 merge来实现这一点,但一直遇到无效的 sql 语句

IF EXISTS (SELECT CustomerID FROM Customer_T WHERE CustomerID = 18)
    Insert into Order_T
    values(79,18,to_date('09/28/2021','mm/dd/yyyy'),to_date('10/01/2021','mm/dd/yyyy'),1,3)
ELSE
  insert INTO Customer_T VALUES (18,'Capitol Industries Ltd', '999 Fifth Avenue', 'New York', 'NY','10015')
  insert into Order_T values (79,18,to_date('09/28/2021','mm/dd/yyyy'),to_date('10/01/2021','mm/dd/yyyy'),1,3)
END IF;

这种情况不需要IF THEN ELSE逻辑。 而是使用数据库内置功能。 customerid 应该是您的主键,因此如果您尝试插入并且它已经存在,则会引发DUP_VAL_ON_INDEX异常。

检查以下示例:

-- create tables
create table customers (
    id                             number generated by default on null as identity 
                                   constraint customers_id_pk primary key,
    name                           varchar2(255 char)
)
;

create table orders (
    id                             number generated by default on null as identity 
                                   constraint orders_id_pk primary key,
    customer_id                    number
                                   constraint orders_customer_id_fk
                                   references customers on delete cascade,
    product                        varchar2(100 char)
)
;

BEGIN
  BEGIN
    insert INTO customers VALUES (2,'Capitol Industries Ltd');
  EXCEPTION WHEN DUP_VAL_ON_INDEX THEN
    NULL; 
  END;
  insert into orders (customer_id,product) values (2,'a book');
END;  
/

运行上面的块几次。 只有第一次它会插入一个客户。

假设您有 2 个非常简单的表。

create table T1( num_ )
as
select 1 from dual ;

create table T2( num_ )
as
select 200 from dual ;

包含 IF.. ELSE.. END IF 和 EXISTS() 的匿名块类似于您问题中的代码,会导致错误:

function 或伪列“EXISTS”只能在 SQL 语句中使用

    begin
      if exists( select num_ from T1 where num_  = 2 ) then
        insert into T2( num_ ) values( 2 ) ;
        dbms_output.put_line( 'if' ) ;
      else
        insert into T1( num_ ) values( 2 ) ;
        insert into T2( num_ ) values( 2 ) ;
        dbms_output.put_line( 'else' ) ;
      end if ;
    end ;
    /
-- error:
... function or pseudo-column 'EXISTS' may be used inside a SQL statement only

一种解决方案可能是执行以下操作(请参阅 asktom.oracle.com - 相当于 IF 语句中的 EXISTS()

begin
  for x in ( select count(*) cnt
             from dual
             where exists ( select num_ from T1 where num_  = 2  ) 
  ) loop
    if ( x.cnt = 1 ) then                  -- found
      insert into T2( num_ ) values( 2 ) ;
      dbms_output.put_line( 'if' ) ;
    else                                   -- not found
      insert into T1( num_ ) values( 2 ) ;
      insert into T2( num_ ) values( 2 ) ;
      dbms_output.put_line( 'else' ) ; 
    end if;
  end loop;
end;
/

-- output:
1 rows affected

dbms_output:
else  

第一次执行匿名块后,表中包含以下行:

select num_, '<- T1' as table_ from T1
union all
select num_, '<- T2' from T2 ;

-- result
NUM_    TABLE_
1       <- T1
2       <- T1
200     <- T2
2       <- T2

再次执行匿名块,你会得到...

1 rows affected

dbms_output:
if

-- tables
NUM_    TABLE_
1       <- T1
2       <- T1
200     <- T2
2       <- T2
2       <- T2

DBfiddle 在这里

您可以使用多表插入并使用这样一个事实,即没有group by聚合 function 在不存在(= 不满足where条件)行的情况下总是返回带有null的行。

代码如下:

 insert into customers(id, name, company, state) values (1, 'Some name', 'Some company', 'NY')

1 行受影响

insert all when cust_exists = 0 then into customers (id, name, company, state) values (cust_id, cust_name, company, state) when 1 = 1 then into orders (id, customer_id, order_date, due_date, some_id) values(order_id, cust_id, order_date, due_date, some_id) select 1 as order_id, 1 as cust_id, 'Some other name' as cust_name, 'Company' as company, 'NY' as state, date '2021-09-28' as order_date, date '2021-10-03' as due_date, 100 as some_id, nvl(max(1), 0) as cust_exists from customers where id = 1

1 行受影响

insert all when cust_exists = 0 then into customers (id, name, company, state) values (cust_id, cust_name, company, state) when 1 = 1 then into orders (id, customer_id, order_date, due_date, some_id) values(order_id, cust_id, order_date, due_date, some_id) select 2 as order_id, 2 as cust_id, 'Some other name' as cust_name, 'Company' as company, 'NY' as state, date '2021-09-28' as order_date, date '2021-10-03' as due_date, 100 as some_id, nvl(max(1), 0) as cust_exists from customers where id = 2

2 行受影响

您还可以使用两个带有记录ignore_row_on_dupkey_index提示的插入,这正如其名称所暗示的那样。

 insert /*+ ignore_row_on_dupkey_index(customers(id)) */ into customers (id, name, company, state) values (2, 'Name', 'Comp', 'NY')

 insert into orders (id, customer_id, order_date, due_date, some_id) values (3, 2, date '2021-09-30', date '2021-10-07', 5)

1 行受影响

select * from customers
ID 姓名 公司 STATE
1个 一些名字 某公司 纽约
2个 其他名字 公司 纽约

db<> 在这里摆弄

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM