如果 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
如果 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