暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 生成序列的触发vs存储Proc

ASKTOM 2020-03-13
341

问题描述



谢谢你给我这个机会

大表有2列,2十亿数据,不断增长,没有分区。一个插入触发器,当在列n1中插入时,它从列2中的值的序列生成nextval。

Column1具有主键,因此我们搜索Column1中是否不存在值,然后插入并最终触发column2的生成值。

在下一个实例中,再次在column1上查询表以获取column2值。

我们使用另一个ETL工具,因此我们处理的记录数量,即我们在column1中调用值存在并检索column2值的次数。

我采用的方法是在外部工具将数据插入表时删除触发器。

Insead我写存储的proc从外部ETL取column1的值,将nextval存储到变量v_sequencevalue中,插入到表值中 (在value1中,v_sequencevalue);

将v_sequencevalue分配给OUT变量并存储到最终表中,这样我就可以避免对这个大表进行额外调用以获取column2的值。

这是在多个数据处理环境中的好方法吗?


专家解答

最佳方法:

* 升级到12c或更高
* 将列设置为具有序列默认值或标识
* 使用返回子句获取值:

create sequence s;
create table t (
  c1 int,
  c2 int
    default s.nextval
);

var v number;
insert into t values ( 1, default )
  returning c2 into :v;

print :v

         V
----------
         1
复制


注意这仅适用于插入... 值。插入...select不支持返回子句。

在升级之前,无论您是使用触发器还是手动分配序列,都取决于您。

就我个人而言,我认为最好在你的插入中使用序列并返回这样的值:

insert into t values ( 999, s.nextval )
  returning c2 into :v;

print :v

         V
----------
         2
复制


这更清楚你的意图,并避免触发开销。但是您可能需要触发器来涵盖未提供序列值的情况。

如果这可能是您关心的问题,则可以定义仅在c2为null时触发的触发器:

drop table t 
  cascade constraints purge;
create table t (
  c1 int,
  c2 int
);

create or replace trigger trig
before insert on t
for each row
when ( new.c2 is null )
begin
  dbms_output.put_line ( 'Fired!' );
  :new.c2 := s.nextval;
end;
/

insert into t values ( 100, s.nextval )
  returning c2 into :v;
  
print :v

         V
----------
         3
  
insert into t ( c1 ) values ( 101 )
  returning c2 into :v;
  
Fired!
  
print :v

         V
----------
         4
复制

文章转载自ASKTOM,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论