ILM中的时间有效性(Temporal Validity)可以让用户依据时间来管理数据的有效性。通过定义数据的有效期,可以达到让只有在有效期内的数据才会被查询出的效果。
此特性可以用来隐藏失效的数据或者那些还未生效的"未来"数据。
目录
一、时间有效性的定义
时间有效性是通过在表上增加2个时间类型的列来进行管理的,通过一个起始时间点和终止时间点来为数据划定一个有效期。你可以显式指定2个列或者由Oracle隐式自动创建。列的创建通过 create table 或 alter table 的period for子句实现。
1.1 Period for 子句语法
语法:
period for valid_time_column [ ( start_time_column, end_time_column ) ]
小括号中的(start_time_column, end_time_column)显示指定用来管理时间有效性的列,也可以省略。省略后,Oracle会自动根据 period for 子句后面的valid_time_column创建出valid_time_column_start 和 valid_time_column_end 两个隐藏列。
1.2 显式指定列
在 create table 时指定有效性时间列,指定表中定义的列:
create table temp_test(
id number,
name varchar2(32),
start_time date,
end_time date,
period for valid_time (start_time, end_time));
或建表后使用 alter table 指定,与上面的效果相同
create table temp_test(
id number,
name varchar2(32),
start_time date,
end_time date);
alter table temp_test add period for valid_time(start_time, end_time);
建表完成后,start_time 和 end_time 即可以用来组合定义数据的有效期。
1.3 有效期数据查询
数据在插入时会根据period for 子句后面的 start_time 和 end_time 划定一个数据有效期的范围,你可以控制在查询时显示所有的数据(像普通表一样),或者仅显示有效期内的数据。
insert into temp_test values(1, 'Vincent', '2020-01-01', '2020-12-31'); -- 有效期为2020年
insert into temp_test values(2, 'Victor', '2021-01-01', '2021-12-31'); -- 有效期为2021年
insert into temp_test values(3, 'Grace', '2021-06-01', null); -- 有效期为2021年6月1日以后
Commit;
你可以查询所有的数据。你也可以在查询时可以通过 as of period for valid_time 来指定一个时间点,限定只有数据的有效期包含这个时间点,数据才能被查询出(即在这个时间点,数据是有效的)。
select * from temp_test as of period for valid_time '2020-03-20'; -- 只有有效期范围包含2020-03-20 这个时间点的数据才会被查询出
select * from temp_test as of period for valid_time '2021-06-01';
select * from temp_test as of period for valid_time '2023-02-01';
1.4 隐式创建列
如果在建表的时候如果不显示指定列,那么Oracle自动会创建隐藏列来进行数据有效性的管理。
create table temp_test(
id number,
name varchar2(32),
period for valid_time);
上面的示例中,在create tables时只指定了period for valid_time,那么Oracle还会自动创建3个隐藏列valid_time, valid_time_start, valid_time_end,这些隐藏列无法通过desc命令查看。
desc temp_test;
但可以通过视图user_tab_cols 来查看:
select table_name, column_name, data_type from user_tab_cols where table_name='TEMP_TEST';
1.5 指定会话级别的有效期
除了通过在查询时通过where或as of period for 子句来过滤数据,也可以通过存储过程dbms_flashback_archive.enable_at_valid_time 在会话级别设定有效期,执行后,整个会话会被设定为你指定的有效时间点。
dbms_flashback_archive.enable_at_valid_time (
level in varchar2,
query_time in timestamp default systtimestamp);
level参数可以设置为3种级别:
- ALL: 显示所有数据,这个是默认的设置。
- CURRENT:只显示当前有效的数据。
- ASOF:只显示一个指定时间点的有效数据
插入不同有效期的数据:
insert into temp_test (id, name, valid_time_start, valid_time_end) values(1, 'Vincent', timestamp '2020-01-01 00:00:00', timestamp '2020-12-31 23:59:59');
insert into temp_test (id, name, valid_time_start, valid_time_end) values(2, 'Victor', timestamp '2021-01-01 00:00:00', timestamp '2021-12-31 23:59:59');
insert into temp_test (id, name, valid_time_start, valid_time_end) values(3, 'Grace', timestamp '2021-06-01 00:00:00', null);
Commit;
将时间有效期设置为ALL,可以查询所有数据,3条数据都被查了出来,这个也是默认设置:
exec dbms_flashback_archive.enable_at_valid_time('ALL');
select * from temp_test;
将时间有效期设置为只显示当前有效数据,只有第3条数据被查了出来:
exec dbms_flashback_archive.enable_at_valid_time('CURRENT');
select * from temp_test;
将时间有效期设置为指定2020年某一时间点,只有第1条数据被查了出来:
exec dbms_flashback_archive.enable_at_valid_time('ASOF', timestamp '2020-07-01 12:32:33');
select * from temp_test;