Sql oracle中的Merge语句问题
我来自Microsoft SQL环境。我有两个表Sql oracle中的Merge语句问题,sql,oracle,sql-merge,Sql,Oracle,Sql Merge,我来自Microsoft SQL环境。我有两个表tak_ne和tak_beb,如果值不存在,我的要求是将值从tak_beb插入tak_ne,如果有,就更新。所以我做了一个如下所示的合并语句。但我现在面临的问题是,每天50000个计数都会增加序列号。Oracle是稳定的数据库,我不知道他们为什么这样做。所以我创建了一个函数并阻止序列号增加。我的问题是,通过创建函数是否是一种正确的方法 merge into tak_ne a using tak_beb b ON (a.NAME=b.NAME) Wh
tak_ne
和tak_beb
,如果值不存在,我的要求是将值从tak_beb
插入tak_ne
,如果有,就更新。所以我做了一个如下所示的合并语句。但我现在面临的问题是,每天50000个计数都会增加序列号。Oracle是稳定的数据库,我不知道他们为什么这样做。所以我创建了一个函数并阻止序列号增加。我的问题是,通过创建函数是否是一种正确的方法
merge into tak_ne a using tak_beb b ON (a.NAME=b.NAME)
When matched then
Update
Set a.AC_NO = b.AC_NO
a.LOCATION = b.LOCATION
a.MODEL = b.MODEL
When not matched then
insert
(
sl_no,
AC_NO,
LOCATION
MODEL
)
Values
(
s_slno_nextval
b.AC_NO
b.LOCATION
b.MODEL
)
然后我创建了一个函数
CREATE OR REPLACE FUNCTION s_slno_nextval
RETURN NUMBER
AS
v_nextval NUMBER;
BEGIN
SELECT s_emp.nextval
INTO v_nextval
FROM dual;
RETURN v_nextval;
END;
Oracle使用这种方法为语句插入的每一行生成唯一的id。TAK_BEB表可能有50000行,因此序列增加50000倍 将增量隐藏到函数中没有帮助。函数被调用并对每一行执行,它再次将序列递增50000次。它增加了开销,从双表中选择50000个 如果确实需要对语句插入的所有行使用序列中的一个值,请使用包变量:
create package single_id_pkg is
id Number;
function get_id return number;
end;
/
create or replace package body single_id_pkg is
function get_id return number is
begin
return id;
end;
end;
/
create trigger tak_ne_BSI_trg
before insert
on tak_ne
begin
select s_emp.nextval
into single_id_pkg.id
from dual;
end;
merge into tak_ne a
using tak_beb b
on (a.NAME=b.NAME)
when matched then
update
set a.AC_NO = b.AC_NO
a.LOCATION = b.LOCATION
a.MODEL = b.MODEL
when not matched then
insert (sl_no,
AC_NO,
LOCATION,
MODEL)
values (single_id_pkg.get_id
b.AC_NO,
b.LOCATION,
b.MODEL)
现在使用表上的before语句触发器设置变量:
create package single_id_pkg is
id Number;
function get_id return number;
end;
/
create or replace package body single_id_pkg is
function get_id return number is
begin
return id;
end;
end;
/
create trigger tak_ne_BSI_trg
before insert
on tak_ne
begin
select s_emp.nextval
into single_id_pkg.id
from dual;
end;
merge into tak_ne a
using tak_beb b
on (a.NAME=b.NAME)
when matched then
update
set a.AC_NO = b.AC_NO
a.LOCATION = b.LOCATION
a.MODEL = b.MODEL
when not matched then
insert (sl_no,
AC_NO,
LOCATION,
MODEL)
values (single_id_pkg.get_id
b.AC_NO,
b.LOCATION,
b.MODEL)
Insert触发器有一个缺点——即使语句只更新行,它也会激发with MERGE子句(请参阅)。如果出现问题,则必须以其他方式初始化变量
接下来,修改语句以使用包变量:
create package single_id_pkg is
id Number;
function get_id return number;
end;
/
create or replace package body single_id_pkg is
function get_id return number is
begin
return id;
end;
end;
/
create trigger tak_ne_BSI_trg
before insert
on tak_ne
begin
select s_emp.nextval
into single_id_pkg.id
from dual;
end;
merge into tak_ne a
using tak_beb b
on (a.NAME=b.NAME)
when matched then
update
set a.AC_NO = b.AC_NO
a.LOCATION = b.LOCATION
a.MODEL = b.MODEL
when not matched then
insert (sl_no,
AC_NO,
LOCATION,
MODEL)
values (single_id_pkg.get_id
b.AC_NO,
b.LOCATION,
b.MODEL)
在Oracle中,使用自动增量字段的标准方法是使用序列。当然,每次你想使用它时,它都会增加序列号。 但是您可以省略调用
sequence\u name.nextval
,将其隐藏在触发器中,这也被认为是标准方法
CREATE OR REPLACE EDITIONABLE TRIGGER TAK_NE_ID_TR"
BEFORE INSERT ON tak_ne
FOR EACH ROW
BEGIN
IF :old.sl_no IS NULL THEN
:new.sl_no := s_emp.nextval;
END IF;
END;
若要为一批插入添加相同的id,可以使用全局临时表进行保存。例如,像这样:
create global temporary table tak_ne_id ("id" number) on commit delete rows
create or replace trigger tak_ne_BSI_trg
before insert
on tak_ne
begin
insert into tak_ne_id("id")
values(s_emp.nextval);
end
create or replace TRIGGER TAK_NE_ID_TR
BEFORE INSERT ON tak_ne
FOR EACH ROW
BEGIN
if :old.sl_no is null then
SELECT "id"
INTO :new.sl_no
FROM tak_ne_id;
end if;
END;
然后,您可以像以前一样使用“合并”,而无需调用nextval
:
merge into tak_ne a using tak_beb b ON (a.NAME=b.NAME)
When matched then
update
set a.AC_NO = b.AC_NO,
a.LOCATION = b.LOCATION,
a.MODEL = b.MODEL
When not matched then
insert
(
AC_NO,
LOCATION,
MODEL
)
Values
(
b.AC_NO,
b.LOCATION,
b.MODEL
);
我会对你的建议进行研究和开发。虽然我在问题中所做的一切都有助于阻止序列每次递增,直到我插入。但我会以你的方式尝试,这将为每一行使用相同的ID,我不确定OP是否希望这样做。我知道他想避免为每个更新的行生成一个序列,但是每个插入的行应该获得相同的ID还是不同的ID?对,在这种情况下,最好是在触发器中直接使用@Mikhailov-set ID from sequence提供一个解,如果ID在从序列中选择之前不为空,因为MERGE语句为每一行触发update和insert触发器ORACLE 12作为标识列