2016-07-28 18 views
0

次の条件に基づいて新しい行がテーブルに挿入されるたびに、インクリメントされる特定の列のレコードを挿入したい 現在の年の値の最初の行:Oracleの非プライマリキー列の自動インクリメント

:1 現在の年のために列の値は

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

私のアプローチは多少このようになりますマッチング年度のその現在の年と次の使用可能な数の第一レコードの1を意味する1 によってインクリメントされなければなりません

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

列の値で挿入されるテーブルの同じ行を更新しますか? – XING

+1

その列は更新されません。 – SantyEssac

答えて

0

あなたはおそらく、このような(私はあなたが年の値を変更することはできないと思う)、挿入のトリガーが必要になります、その場合は、より複雑になります)。取引のカップルが同じ年に同時に実行している場合は、重複を持っている可能性があるので、この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

現在のテーブル値を調べるソリューションは、複数のユーザーと複数のセッションと並列トランザクションを持つ「実際の」環境では機能しません。

私はあなたでは次の2つの要件を分離する必要があると思う:

  1. は、それらが
  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 

OK - すべてが正常に動作しますが、doesnのように、

これは第2の部分です:報告要件:

最初のオプションはちょうどあなたが動的に必要な数値を得ることです:分析関数(この場合はrow_number)を使用して

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; 

は、この種のものを処理するための素晴らしい方法です。

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に仮想列がありますが、これらは解析機能では機能しません。私のオプションは、ここにマテリアライズド・ビューを使用することです - マテリアライズド・ビューのリフレッシュを処理する方法の多くをし、最も単純なものは、次のようになります。

exec dbms_mview.refresh('analysis_data_mv'); 

:マテリアライズド・ビューを手動で更新されるだろう。この場合

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 

お役に立てれば。

+0

非常にうまく説明されています。あなたの答えをアップアップ。 – XING

関連する問題