在其他系统中,其实已经有很多地方用到了生命周期管理,而时间有效期管理(Temporal Validity)也是属于生命周期管理当中的一种,当然其他还有数据的生命周期管理,比如数据库内归档(In-Database Archiving)等。还有一些比如数据库分区,转移历史数据等,也算是一种数据生命周期管理,下面看一下Oracle 12C新特性中的时间有效期管理。
可以这样简单的理解:Temporal Validity实际上就是在一个表中,系统自动或者手动添加2个时间类型的列,一个表示有效期的开始时间(默认列名是根据period for参数后面跟的名字加上start,比如period for valid_time,那么有效期的开始时间默认名字就是valid_time_start),另一个表示有效期的结束时间(默认列名同有效期的开始时间名字,只不过后面跟的是end),当然这个也可以手工指定列名,而且这2个列名可以不是隐藏的列(PS:但一般在环境中还是指定为隐藏的列,这样也避免混淆),通过这2个列,就可以设置让只有在有效期内的数据才展示。需要在创建表的时候指定period for关键字,如果没有手工指定列名,那么系统会自动创建2个不可见的字段,也就是user_time_start和user_time_end。下面来看一下在12C中如何使用这个特性。
1. 创建一个时间有效期管理的表,且系统自动指定时间有效期管理列
1 2 3 4 5 6 7 8 9 10 11 12 |
SQL> create table jerry_temporal_validity( 2 transaction_id number, 3 transaction_name varchar2(20), 4 period for user_time); Table created. SQL> desc jerry_temporal_validity Name Null? Type ----------------------------------------- -------- ---------------------------- TRANSACTION_ID NUMBER TRANSACTION_NAME VARCHAR2(20) |
2. 在创建的jerry_temporal_validity表中,指定了period for参数,但这里没有指定时间有效期管理的列名,用desc方式查看的时候,也查看不到列,因为自动创建的时间有效期管理的列是隐藏列
1 2 3 4 5 6 7 8 9 |
SQL> select table_name,column_name from dba_tab_cols where table_name=upper('jerry_temporal_validity'); TABLE_NAME COLUMN_NAME ------------------------------ -------------------- JERRY_TEMPORAL_VALIDITY TRANSACTION_NAME JERRY_TEMPORAL_VALIDITY TRANSACTION_ID JERRY_TEMPORAL_VALIDITY USER_TIME JERRY_TEMPORAL_VALIDITY USER_TIME_END JERRY_TEMPORAL_VALIDITY USER_TIME_START |
可以看到在数据字典中,jerry_temporal_validity表多了2个列。
3. 在jerry_temporal_validity表中插入数据,查看数据展示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
SQL> insert into jerry_temporal_validity values(1,'jerry'); 1 row created. SQL> insert into jerry_temporal_validity values(2,'tom'); 1 row created. SQL> commit; Commit complete. SQL> select * from jerry_temporal_validity; TRANSACTION_ID TRANSACTION_NAME -------------- -------------------- 1 jerry 2 tom SQL> select TRANSACTION_NAME,TRANSACTION_ID,USER_TIME_START,USER_TIME_END from jerry_temporal_validity; TRANSACTION_NAME TRANSACTION_ID USER_TIME_START USER_TIME_END -------------------- -------------- -------------------- -------------------- jerry 1 tom 2 SQL> insert into jerry_temporal_validity(TRANSACTION_NAME,TRANSACTION_ID,USER_TIME_START,USER_TIME_END) values ('aa',3,to_date('2014-07-13','yyyy-mm-dd'),to_date('2014-07-14','yyyy-mm-dd')); 1 row created. SQL> insert into jerry_temporal_validity(TRANSACTION_NAME,TRANSACTION_ID,USER_TIME_START,USER_TIME_END) values ('bb',4,to_date('2014-07-13','yyyy-mm-dd'),to_date('2014-07-14','yyyy-mm-dd')); 1 row created. SQL> select TRANSACTION_NAME,TRANSACTION_ID,USER_TIME_START,USER_TIME_END from jerry_temporal_validity; TRANSACTION_NAME TRANSACTION_ID USER_TIME_START USER_TIME_END -------------------- -------------- -------------------- -------------------- jerry 1 tom 2 aa 3 13-JUL-14 12.00.00.0 14-JUL-14 12.00.00.0 00000 AM -04:00 00000 AM -04:00 bb 4 13-JUL-14 12.00.00.0 14-JUL-14 12.00.00.0 00000 AM -04:00 00000 AM -04:00 |
在第一次插入数据的是,没有插入时间有效期管理的列,由于系统自动创建这2个列的时候,没有指定default值,所以我们这里看到的表这2列没有数据,在第二次插入的时候,显示指定了插入时间有效期管理的列。
4. 在查询的时候,可以指定period for显示指定时间的列
1 2 3 4 5 6 7 8 9 10 11 |
SQL> select TRANSACTION_NAME,TRANSACTION_ID,USER_TIME_START,USER_TIME_END from jerry_temporal_validity as of period for user_time to_date('2014-07-13','yyyy-mm-dd'); TRANSACTION_NAME TRANSACTION_ID USER_TIME_START USER_TIME_END -------------------- -------------- -------------------- -------------------- jerry 1 tom 2 aa 3 13-JUL-14 12.00.00.0 14-JUL-14 12.00.00.0 00000 AM -04:00 00000 AM -04:00 bb 4 13-JUL-14 12.00.00.0 14-JUL-14 12.00.00.0 00000 AM -04:00 00000 AM -04:00 |
在指定日期的时候,也可以用between and指定一个时间段的数据。另外还可以通过dbms_flashback_archive包来指定时间段,比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
SQL> exec DBMS_FLASHBACK_ARCHIVE.ENABLE_AT_VALID_TIME('ASOF',to_date('2014-07-13','yyyy-mm-dd')); PL/SQL procedure successfully completed. SQL> select TRANSACTION_NAME,TRANSACTION_ID,USER_TIME_START,USER_TIME_END from jerry_temporal_validity; TRANSACTION_NAME TRANSACTION_ID USER_TIME_START USER_TIME_END -------------------- -------------- -------------------- -------------------- jerry 1 tom 2 aa 3 13-JUL-14 12.00.00.0 14-JUL-14 12.00.00.0 00000 AM -04:00 00000 AM -04:00 bb 4 13-JUL-14 12.00.00.0 14-JUL-14 12.00.00.0 00000 AM -04:00 00000 AM -04:00 bb 4 13-JUL-13 12.00.00.0 14-JUL-14 12.00.00.0 00000 AM -04:00 00000 AM -04:00 |
在DBMS_FLASHBACK_ARCHIVE.ENABLE_AT_VALID_TIME中也可以直接指定current或者all。
另外还有一种手工指定时间有效期管理的列,这种方式的好处就是可以指定default值,比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
SQL> create table jerry_temporal_validity2( 2 transaction_id number, 3 transaction_name varchar2(20), 4 valid_time_start date invisible default sysdate, 5 valid_time_end date invisible default sysdate, 6 period for valid_time(valid_time_start,valid_time_end)); Table created. SQL> desc jerry_temporal_validity2 Name Null? Type ----------------------------------------------------------------------------------------------------------------- -------- ---------------------------------------------------------------------------- TRANSACTION_ID NUMBER TRANSACTION_NAME SQL> select table_name,column_name from dba_tab_cols where table_name=upper('jerry_temporal_validity2'); TABLE_NAME COLUMN_NAME ------------------------------ -------------------- JERRY_TEMPORAL_VALIDITY2 VALID_TIME_END JERRY_TEMPORAL_VALIDITY2 VALID_TIME_START JERRY_TEMPORAL_VALIDITY2 TRANSACTION_NAME JERRY_TEMPORAL_VALIDITY2 TRANSACTION_ID JERRY_TEMPORAL_VALIDITY2 VALID_TIME |
当然管理的方式和自动创建的时间有效期的列是一样的,只不过可以不用手动插入这2个隐藏列的值,更倾向于这种手工指定列的方式。
不过在使用这个特性的时候也需要注意,因为这个可能给系统带来性能的影响,大家可以通过查看执行计划的方式来查看使用了有效时间管理的查询和没有使用这个特性的查询,这2中的执行计划是不一样的,而且在一个有索引的表中,可能导致全表扫描,因为filter不一样了。所以在使用这个功能的时候,数据库架构人员在计划的时候一定要考虑到性能方面的因素。
- 本文固定链接: http://www.savedba.com/?p=785
- 转载请注明: 版权所有,文章允许转载,但必须以链接方式注明源地址,否则追究法律责任!