2016-07-28 49 views
0

我想插入一个特定列的记录,每当新行插入表中时,将根据以下条件增加1 对于当前年份,第一行包含值:1 ,本年度列的值应该由1 意味着1年,目前年度的1记录和下一个可用的号码匹配对于Oracle中的非主键列自动递增

Year Value 
2016 1 
2016 2 
2016 3 
2017 1 
2017 2 
... 

我的做法会有些这样可以增加:

INSERT INTO ABC(ANALYSIS_YEAR,ANALYSIS_NUMBER) 
values (EXTRACT(YEAR FROM sysdate), 
     case when ANALYSIS_YEAR=EXTRACT(YEAR FROM sysdate) then AutoIcreamt with starting value 1 else 1; 
    ) 
+0

是否要更新以列值插入的表中的同一行1 – XING

+1

否该列不会更新 – SantyEssac

回答

0

你可能需要一个插入触发器,看起来像这样(我猜你不能改变Year的值,在这种情况下它会变得更复杂)。 像@ ibre5041这不会在多用户环境工作,因为如果一对夫妇的交易都在同一时间在同一年执行,你可以有重复:

CREATE OR REPLACE TRIGGER trg_bi_table1 
before insert 
ON table_1 
Begin 
    select nvl(max(value),0)+1 as value 
    into :new.value 
    from table_1 
    where Year = :new.Year; 
end; 
/

在多用户环境,你应使用select for update

+0

该请求是插入一行。你的触发器如何在表格中插入一行?我想你需要提供完整的解决方案 – XING

+0

@Raj_Te我认为他正在寻找名为'Value'的列的自动增量。 – vercelli

+0

在这种情况下,以及年份发生变化时,您的上述触发器将不会重置为1. – XING

2

任何查看当前表值的解决方案都不适用于包含多个用户和多个会话以及并行事务的“真实”环境。

我认为你需要分离出两个要求:

  1. 不得不基于序列的时候被创建
  2. 不得不在一年内记录排序报告的能力上记录的能力。

首先是使用序列因为这些正是为此设计和处理并发(多用户,多笔交易,...)来处理。

第二个是报告要求,根据性能要求有多个选项。

首先创建一个序列:

create sequence seq_analysis_id start with 1 increment by 1 nocache nocycle; 

不是让我们创建一个基表和触发器来处理自动递增:

create table analysis_data (
    analysis_id integer not null, 
    analysis_date date not null 
    ); 

alter table analysis_data add constraint pk_analysis_data primary key (analysis_id); 

create or replace trigger trg_analysis_data 
before insert on analysis_data 
for each row 
begin 
    :new.analysis_id := seq_analysis_id.nextval(); 
end trg_analysis_data; 
/

insert into analysis_data (analysis_date) values (to_date('2015-12-28', 'YYYY-MM-DD')); 

insert into analysis_data (analysis_date) values (to_date('2015-12-29', 'YYYY-MM-DD')); 

insert into analysis_data (analysis_date) values (to_date('2015-12-30', 'YYYY-MM-DD')); 

insert into analysis_data (analysis_date) values (to_date('2015-12-31', 'YYYY-MM-DD')); 

insert into analysis_data (analysis_date) values (to_date('2016-01-01', 'YYYY-MM-DD')); 

insert into analysis_data (analysis_date) values (to_date('2016-01-02', 'YYYY-MM-DD')); 

insert into analysis_data (analysis_date) values (to_date('2016-01-03', 'YYYY-MM-DD')); 

commit; 

select * from analysis_data; 

ANALYSIS_ID ANALYSIS_DATE 
    1   28/12/2015 
    2   29/12/2015 
    3   30/12/2015 
    4   31/12/2015 
    5   01/01/2016 
    6   02/01/2016 
    7   03/01/2016 

好 - 让所有工作正常,但没有按给你所要求的:)

这是第二部分 - 报告要求:

第一个选项是刚拿到号码,你需要动态:

select 
    analysis_id, 
    analysis_date, 
    extract(year from analysis_date) analysis_year, 
    row_number() 
     over (partition by trunc(analysis_date, 'YYYY') 
     order by analysis_date, analysis_id) analysis_number 
from 
    analysis_data; 

使用解析函数(row_number在这种情况下)是处理这种事情的好方法。

ANALYSIS_ID ANALYSIS_DATE ANALYSIS_YEAR ANALYSIS_NUMBER 
    1   28/12/2015  2015    1 
    2   29/12/2015  2015    2 
    3   30/12/2015  2015    3 
    4   31/12/2015  2015    4 
    5   01/01/2016  2016    1 
    6   02/01/2016  2016    2 
    7   03/01/2016  2016    3 

我已在row_number函数中订购analysis_date, analysis_id。这可能不是必需的,但如果您必须处理analysis_date的更新(在这种情况下,序列不再适用于年内订购),则可能需要此选项。

您可以通过在视图中包装它使本作的报告有点更直截了当:

create or replace view analysis_data_v as 
select 
    analysis_id, 
    analysis_date, 
    extract(year from analysis_date) analysis_year, 
    row_number() 
     over (partition by trunc(analysis_date, 'YYYY') 
     order by analysis_date, analysis_id) analysis_number 
from 
    analysis_data; 

这可能是你所需要的,但如果你有大量的数据集,那么你可能需要预先计算其中一些价值。您有11g中的虚拟列,但这些不适用于分析功能。在这里,我的选择是使用物化视图 - 很多方法来处理物化视图刷新,最简单的是:

create materialized view analysis_data_mv 
    build immediate 
    refresh complete on demand 
as 
    select 
     analysis_id, 
     analysis_date, 
     analysis_year, 
     analysis_number 
    from 
     analysis_data_v; 

select * from analysis_data_mv order by analysis_year, analysis_number; 

ANALYSIS_ID ANALYSIS_DATE ANALYSIS_YEAR ANALYSIS_NUMBER 
    1   28/12/2015  2015    1 
    2   29/12/2015  2015    2 
    3   30/12/2015  2015    3 
    4   31/12/2015  2015    4 
    5   01/01/2016  2016    1 
    6   02/01/2016  2016    2 
    7   03/01/2016  2016    3 

在这种情况下,物化视图就可以手动刷新:

exec dbms_mview.refresh('analysis_data_mv'); 

希望这可以帮助。

+0

非常好的解释。 Upvoted为您的答案。 – XING