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

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

如果 table A 中存在客户 ID,请在 table B 中插入订单。 如果tableA中不存在customer id,请在tableA中插入customer id,然后在[=中下单31=]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;

假设您有 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 or pseudo-column 'EXISTS' may be used inside a SQL statement only

    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 - Equivalent for EXISTS() in an IF statement

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 here.

这种情况不需要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;  
/

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

您可以使用 multitable insert 并使用这样一个事实,即没有 group by 的聚合函数总是 returns 一行 null 在不存在的情况下(= 不满足 where 条件) 行.

代码如下:

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

1 rows affected

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 rows affected

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 rows affected

您也可以使用带有 documented 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 rows affected

select *
from customers
ID NAME COMPANY STATE
1 Some name Some company NY
2 Some other name Company NY

db<>fiddle here