范围分区允许用户根据分区键列值的范围创建分区。下面是一个按范围分区表的示例:
create table sales6
(
sales_id number,
sales_dt date
)
partition by range (sales_dt)
(
partition p0701 values less than (to_date('2007-02-01','yyyy-mm-dd')),
partition p0702 values less than (to_date('2007-03-01','yyyy-mm-dd'))
);
假如在此处仅针对2007年1月和2007年2月定义了分区,如果表中插入一条sales_dt在2007年3月的记录,会发生什么情况?插入将失败,并显示以下错误:
ORA-14400: inserted partition key does not map to any partition
显然,需要针对2007年3月添加一个分区,然后才能插入一条记录。但通常说起来容易做起来难。通常无法容忍事先创建大量分区,但其中很少一部分可能会产生此错误。
如果Oracle以某种方式自动察觉到对新分区的需要,然后创建它们,这样不是更好吗?Oracle 11g可以,它可以使用一个称为间隔分区的特性。此时,不必定义分区及它们的边界,只需定义一个定义了每个分区边界的间隔。下面是使用间隔分区的示例:
create table sales6
(
sales_id number,
sales_dt date
)
partition by range (sales_dt)
interval (numtoyminterval(1,'MONTH'))
(
partition p0701 values less than (to_date('2007-02-01','yyyy-mm-dd'))
);
注意子句interval后面跟着时间间隔,在此处指示Oracle为每个月份创建一个时间间隔。已经为2007年1月的数据创建了名为p0701的初始分区。现在,假设插入了一条包括2007年6月数据的记录:
SQL> insert into sales6 values (1,'01-jun-07');
1 row created.
Oracle不会返回错误,而是成功执行该语句。那么这条记录将转向何处?p0701 分区不能包括该记录,因为没有为2007年6月定义分区。但此时,如果检查该表的分区:
SQL> select partition_name, high_value
2 from user_tab_partitions
3 where table_name = 'SALES6';
PARTITioN_NAME HIGH_VALUE
----------------------------------------------------------------
P0701 TO_DATE(' 2007-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_C
ALENDAR=GREGORIA
SYS_P41 TO_DATE(' 2007-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_C
ALENDAR=GREGORIA
注意名为SYS_P1、HIGH_VALUE为2007年7月1日分区,它最多可以容纳到6月底的数据。该分区是由Oracle动态创建的,并具有一个系统生成的名称。
现在,假设输入一个小于HIGH_VALUE的值,如2007年5月1日。在理想情况下,它应该具有自己的分区,因为分区时间间隔是一个月。
SQL> insert into sales6 values (1,'01-may-07');
1 row created.
SQL> select partition_name, high_value
2 from user_tab_partitions
3 where table_name = 'SALES6';
PARTITioN_NAME HIGH_VALUE
----------------------------------------------------------------
P0701 TO_DATE(' 2007-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_C
ALENDAR=GREGORIA
SYS_P41 TO_DATE(' 2007-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_C
ALENDAR=GREGORIA
SYS_P42 TO_DATE(' 2007-06-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_C
ALENDAR=GREGORIA
注意新分区SYS_P42,其上限为6月1日,因此该分区可以保留2006年5月的数据。该分区是通过拆分SYS_P41分区创建的(针对6月份)。因此,当定义一个间隔分区方案时,Oracle会自动创建和维护分区。
如果希望将分区存储在特定表空间中,可以使用store in子句执行该操作:
interval (numtoyminterval(1,'MONTH'))
store in (TS1,TS2,TS3)
该子句以循环方式将分区存储在表空间TS1、TS2和TS3中。
应用程序开发人员如何定位特定分区?一种方法是知道名称,这种方法可能不可行,即使知道名称,这种方法也非常容易出错。为了便于访问特定分区,Oracle 11g为分区SQL提供了一个新语法:
SQL> select * from sales6 partition for (to_date('15-may-2007','dd-mon-yyyy'));
SALES_ID SALES_DT
---------- ---------
1 01-MAY-07
注意新子句for(值),它允许用户直接引用分区,而不必通过它们的准确名称进行显式调用。如果希望截断或删除一个分区,可以调用这个扩展的分段语法。
以此方式创建表之后,DBA_PART_TABLES 视图中的 PARTITIONING_TYPE 列会显示时间间隔