我希望插入特定列的记录,只要根据以下条件将新行插入表中,该列就会递增1 对于当前年份,第一行的值为:1 对于当前年份,列值应增加1 意味着当前年度的第一条记录 1,匹配年份的下一个可用数字
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 :(得分: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
我已在analysis_date, analysis_id
函数中row_number
订购了。这可能不是必要的,但如果您必须处理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');
希望这有帮助。
答案 1 :(得分: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