2016-07-28 103 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