范圍分區允許用戶根據分區鍵列值的范圍創建分區。下面是一個按范圍分區表的示例:
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 列會顯示時間間隔