【12c】新特性:Oracle 12c Temporal Validity 时间有效性

在应用程序开发中,有时会碰到这样一个场景:设置一条记录的生效时间范围,比如某个产品信息,在某个时间段内是有效的,一般设计表时会在表中增加valid_start和valid_end这两个字段来限制,并通过设置这两个字段来实现具体产品的生效范围,如果查看当前生效的记录,则需要通过时间进行过滤。

Oracle 12.1.0.1引入了Temporal Validity(时间有效性),通过这一特性,在不增加列的情况下可以实现时间有效性的的判断,下面将对这一特性进行演示。

1 数据库版本

ALEN@PROD2> select * from v$version;



BANNER CON_ID

-------------------------------------------------------------------------------- ----------

Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production 0

PL/SQL Release 12.1.0.2.0 - Production 0

CORE 12.1.0.2.0 Production 0

TNS for Linux: Version 12.1.0.2.0 - Production 0

NLSRTL Version 12.1.0.2.0 - Production 0

2 语法结构

要实现时间有效性,在创建表或修改表时指定如下语法即可:

 

说明:

  • valid_time_column:用于指定有效时间维度的名称,Oracle将会使用该名称创建数据类型为number的不可见虚拟列;
  • start_time_column:指定起始时间列的名称,数据类型为date或timestamp;
  • end_time_column:指定结束时间列的名称,数据类型为date或timestamp;
  • 如果不指定start_time_column和end_time_column,则会自动创建valid_time_column_START和valid_time_column_END列。

3 创建表

3.1 不指定start_time_column和end_time_column

ALEN@PROD2> create table prod(id number,name varchar2(100),period for valid);



Table created.

ALEN@PROD2> desc prod

Name Null? Type

----------------------- -------- ----------------

ID NUMBER

NAME VARCHAR2(100)

ALEN@PROD2> select column_name,data_type,data_length,column_id,segment_column_id, hidden_column from user_tab_cols where table_name='PROD';



COLUMN_NAME DATA_TYPE DATA_LENGTH COLUMN_ID SEGMENT_COLUMN_ID HIDDEN_COL

------------------------------ ------------------------------ ----------- ---------- ----------------- ----------

NAME VARCHAR2 100 2 4 NO

ID NUMBER 22 1 3 NO

VALID NUMBER 22 YES

VALID_END TIMESTAMP(6) WITH TIME ZONE 13 2 YES

VALID_START TIMESTAMP(6) WITH TIME ZONE 13 1 YES

3.2 指定start_time_column和end_time_column

ALEN@PROD2> create table prod_new(id number,name varchar2(100),valid_start_dt date, valid_end_dt date, period for valid (valid_start_dt,valid_end_dt));



Table created.

ALEN@PROD2> desc prod_new;

Name Null? Type

----------------------- -------- ----------------

ID NUMBER

NAME VARCHAR2(100)

VALID_START_DT DATE

VALID_END_DT DATE

ALEN@PROD2> select column_name,data_type,data_length,column_id,segment_column_id, hidden_column from user_tab_cols where table_name='PROD_NEW';



COLUMN_NAME DATA_TYPE DATA_LENGTH COLUMN_ID SEGMENT_COLUMN_ID HIDDEN_COL

------------------------------ ------------------------------ ----------- ---------- ----------------- ----------

VALID NUMBER 22 YES

ID NUMBER 22 1 1 NO

NAME VARCHAR2 100 2 2 NO

VALID_START_DT DATE 7 3 3 NO

VALID_END_DT DATE 7 4 4 NO

4 创建测试数据

ALEN@PROD2> insert into prod(id,name,valid_start,valid_end) values(1,'Apple_01',date'2019-01-01',date'2019-10-31');



1 row created.



ALEN@PROD2> insert into prod(id,name,valid_start,valid_end) values(2,'Car',date'2020-01-01',date'2020-05-01');



1 row created.



ALEN@PROD2> insert into prod(id,name,valid_start,valid_end) values(3,'现金贷',date'2020-03-01',date'2020-11-01');



1 row created.



ALEN@PROD2> insert into prod(id,name,valid_start,valid_end) values(4,'消费贷',date'2019-03-01',null);



1 row created.



ALEN@PROD2> commit;



Commit complete.

5 查询数据

ALEN@PROD2> select id,name,trunc(valid_start),trunc(valid_end) from prod;



ID NAME TRUNC(VALID_START) TRUNC(VALID_END)

---------- -------------------- ------------------- -------------------

1 Apple_01 2019-01-01 00:00:00 2019-10-31 00:00:00

2 Car 2020-01-01 00:00:00 2020-05-01 00:00:00

3 现金贷 2020-03-01 00:00:00 2020-11-01 00:00:00

4 消费贷 2019-03-01 00:00:00

6 检索数据

6.1 普通查询方式

SQL> select * from prod where date '2019-05-01' between valid_start and nvl(valid_end,sysdate);



ID NAME

---------- --------------------

1 Apple_01

4 消费贷

6.2 SELECT... AS OF方式

ALEN@PROD2> select * from prod as of period for valid date'2020-03-01';



ID NAME

---------- --------------------

2 Car

3 现金贷

4 消费贷



ALEN@PROD2> select * from prod as of period for valid date '2019-10-31';



ID NAME

---------- --------------------

4 消费贷

6.2 SELECT... VERSIONS BETWEEN方式

ALEN@PROD2> select * from prod versions period for valid between date '2020-03-01' and date '2020-05-01';



ID NAME

---------- --------------------

2 Car

3 现金贷

4 消费贷

7 会话级别的可见性控制

除了使用闪回查询、闪回版本查询数据之外,还可以通过dbms_flashback_archive的存储过程ENABLE_AT_VALID_TIME在会话级别指定表数据的可见性:显示所有数据(默认),显示指定时间的有效数据或者显示当前的有效数据。

1)默认显示所有数据

ALEN@PROD2> select * from prod;



ID NAME

---------- --------------------

1 Apple_01

2 Car

3 现金贷

4 消费贷

2)显示指定时间的数据

ALEN@PROD2> exec dbms_flashback_archive.enable_at_valid_time('ASOF',date '2019-09-01');



PL/SQL procedure successfully completed.



ALEN@PROD2> select id,name from prod;



ID NAME

---------- --------------------

1 Apple_01

4 消费贷

3)显示当前时间可见的数据

ALEN@PROD2> exec dbms_flashback_archive.enable_at_valid_time('CURRENT');



PL/SQL procedure successfully completed.



ALEN@PROD2> select id,name from prod;



ID NAME

---------- --------------------

3 现金贷

4 消费贷

4)显示所有数据

ALEN@PROD2> exec dbms_flashback_archive.enable_at_valid_time('ALL');



PL/SQL procedure successfully completed.

ALEN@PROD2> select id,name from prod;



ID NAME

---------- --------------------

1 Apple_01

2 Car

3 现金贷

4 消费贷

以上就是Oracle 12c关于时间有效性的介绍,在使用时需要注意隐藏字段以及SQL中条件的正确判断。

posted @ 2020-05-22 20:28  追梦男生  阅读(394)  评论(0编辑  收藏  举报