You are on page 1of 5

Interval Partitioning in 11g

is a extension of range partitioning. They automate creation of equi-sized partitions. Partitions


are created as metadata and only the initial partition is made persistent.Additional partitions and
local indexes are created automatically when the data is inserted.

Example :

-- CREATE TABLE
CREATE TABLE INVOICES
(
INVOICE_NO NUMBER NOT NULL,
INVOICE_DATE DATE NOT NULL,
COMMENTS VARCHAR2(500)
)
PARTITION BY RANGE (INVOICE_DATE)
INTERVAL (NUMTOYMINTERVAL(1,'MONTH'))
(PARTITION P_FIRST VALUES LESS THAN ('01-JAN-2008') TABLESPACE USERS);

-- create indexes
CREATE UNIQUE INDEX INVNO_UNQ_IDX ON INVOICES(INVOICE_NO,INVOICE_DATE)

LOCAL (PARTITION P_FIRST TABLESPACE USERS);

The line "INTERVAL (NUMTOYMINTERVAL(1,'MONTH'))" indicates the table is partitioned by


Monthly intervals of INVOICE_DATE.

The Function NUMTOYMINTERVAL function converts a number to an INTERVAL YEAR TO


MONTH literal.In this context it indicates an interval of 1 month.Likewise, For yearly partitions
use the keyword "YEAR" on the same function.

Also the function NUMTODSINTERVAL will be used to create partitions with intervals of
"WEEK","DAY","HOUR","MINUTE","SECOND".

To Create a weekly partition the syntax would be


PARTITION BY RANGE (INVOICE_DATE)
INTERVAL (NUMTODSINTERVAL(7,'DAY')).

Querying the table "USER_TAB_PARTITIONS" will show one partition created.


SQL> SELECT TABLE_NAME,
PARTITION_NAME,
HIGH_VALUE
FROM USER_TAB_PARTITIONS
WHERE TABLE_NAME = 'INVOICES'
ORDER BY TABLE_NAME, PARTITION_NAME;
TABLE_NAME PARTITION_NAME HIGH_VALUE
-------------------- -------------------- ----------------------------------------
INVOICES P_FIRST TO_DATE(' 2008-01-01 00:00:00', 'SYYYY-M
M-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')

-- Insert statements for Invoice Data


SQL> INSERT INTO INVOICES VALUES(1,TO_DATE('16-JAN-2008','DD-MON-YYYY'), 'Test
Invoice1');
SQL> INSERT INTO INVOICES VALUES(1,TO_DATE('16-FEB-2008','DD-MON-YYYY'), 'Test
Invoice2');

SQL> COMMIT;

Adding data beyond the range of the initial partition(P_FIRST) will create new partitions as
shown below.

SQL> SELECT TABLE_NAME,


PARTITION_NAME,
HIGH_VALUE
FROM USER_TAB_PARTITIONS
WHERE TABLE_NAME = 'INVOICES'
ORDER BY TABLE_NAME, PARTITION_NAME;

TABLE_NAME PARTITION_NAME HIGH_VALUE


-------------------- -------------------- ----------------------------------------
INVOICES P_FIRST TO_DATE(' 2008-01-01 00:00:00', 'SYYYY-M
M-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')

INVOICES SYS_P4008 TO_DATE(' 2008-02-01 00:00:00', 'SYYYY-M


M-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')

INVOICES SYS_P4009 TO_DATE(' 2008-03-01 00:00:00', 'SYYYY-M


M-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')

If data is inserted later than the current maximum high value(say like 6 months ahead),only the
required partition is created, not the intermediate partitions.

SQL> INSERT INTO INVOICES VALUES(3,TO_DATE('16-JUL-2008', 'DD-MON-YYYY'),


'Test Invoice3');

SQL> COMMIT;

SQL> SELECT TABLE_NAME,


PARTITION_NAME,
HIGH_VALUE
FROM USER_TAB_PARTITIONS
WHERE TABLE_NAME = 'INVOICES'
ORDER BY TABLE_NAME, PARTITION_NAME;

TABLE_NAME PARTITION_NAME HIGH_VALUE


------------------- -------------------- ----------------------------------------
INVOICES P_FIRST TO_DATE(' 2008-01-01 00:00:00', 'SYYYY-M
M-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')

INVOICES SYS_P4008 TO_DATE(' 2008-02-01 00:00:00', 'SYYYY-M


M-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')

INVOICES SYS_P4009 TO_DATE(' 2008-03-01 00:00:00', 'SYYYY-M


M-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')

INVOICES SYS_P4010 TO_DATE(' 2008-08-01 00:00:00', 'SYYYY-M


M-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')

The partition is created is for the month of "2008-07" and not for the intermediate months
between "2009-03" and "2009-08".

Converting Range-Partitioned Table to Interval Partitioned Table:


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

SQL>CREATE TABLE SALES


(
SALES_NO NUMBER,
SALE_DATE DATE NOT NULL
)
PARTITION BY RANGE (SALE_DATE)
(PARTITION P_FIRST VALUES LESS THAN ('01-JAN-2008') TABLESPACE USERS);

-- The following alter table statement will change a range-partitioned table to interval partitioned
based on the interval provided(yearly in this case).

SQL>ALTER TABLE SALES SET INTERVAL (NUMTOYMINTERVAL(1,'YEAR'));

Disabling Interval Partition:


----------------------------
In order to disable interval partitioning on the SALES table,

SQL>ALTER TABLE SALES SET INTERVAL ();

The table will go back to range partitioned where you have to manually add partitions.
Manually adding a partition to a Interval Partitioned Table:
-------------------------------------------------------------
The database automatically creates a partition for an interval when data for that interval is
inserted.But if there's a scenario for a partition exchange where you need to explicitly create
interval partitions you can do it by using the "lock table partition for command shown below.

Create a staging table for invoices called "INVOICES_STAGING" that holds invoices for the
month of August,2008

SQL>
CREATE TABLE INVOICES_STAGING
(
INVOICE_NO NUMBER NOT NULL,
INVOICE_DATE DATE NOT NULL,
COMMENTS VARCHAR2(500)
);

SQL>INSERT INTO INVOICES_STAGING VALUES(5,TO_DATE('18-AUG-2008', 'DD-MON-


YYYY'), 'Test Invoice4');

SQL>INSERT INTO INVOICES_STAGING VALUES(6,TO_DATE('21-AUG-2008', 'DD-MON-


YYYY'), 'Test Invoice5');

SQL>INSERT INTO INVOICES_STAGING VALUES(7,TO_DATE('31-AUG-2008', 'DD-MON-


YYYY'), 'Test Invoice6');

SQL> COMMIT;

The data from the staging table "INVOICES_STAGING" can now be exchanged onto the main
"INVOICES" table.

First, manually create the partition on the main "INVOICES" table using the following lock
command

SQL> LOCK TABLE invoices PARTITION FOR(TO_DATE('01-AUG-2008','dd-MON-yyyy')) IN


SHARE MODE;
SQL> COMMIT;

Check to see if the partition for August 2008 is created

SQL> SELECT TABLE_NAME,


PARTITION_NAME,
HIGH_VALUE
FROM USER_TAB_PARTITIONS
WHERE TABLE_NAME = 'INVOICES'
ORDER BY TABLE_NAME, PARTITION_NAME;
TABLE_NAME PARTITION_NAME HIGH_VALUE
-------------------- -------------------- ----------------------------------------
INVOICES P_FIRST TO_DATE(' 2008-01-01 00:00:00', 'SYYYY-M
M-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')

INVOICES SYS_P4008 TO_DATE(' 2008-02-01 00:00:00', 'SYYYY-M


M-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')

INVOICES SYS_P4009 TO_DATE(' 2008-03-01 00:00:00', 'SYYYY-M


M-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')

INVOICES SYS_P4010 TO_DATE(' 2008-08-01 00:00:00', 'SYYYY-M


M-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')

INVOICES SYS_P4013 TO_DATE(' 2008-09-01 00:00:00', 'SYYYY-M


M-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')

The last partition "SYS_P4013" is the partition creating using the lock command.

Exchange the data for August,2008 from the staging table "INVOICES_STAGING" to the main
table "INVOICES" using the following alter command.

SQL>ALTER TABLE invoices


EXCHANGE PARTITION FOR (TO_DATE('01-AUG-2008','dd-MON-yyyy'))
WITH TABLE invoices_staging
EXCLUDING INDEXES
WITHOUT VALIDATION;

-- The data for the month of August 2008 is exchanged into "INVOICES" table
SQL> select t.invoice_no,t.invoice_date from invoices t;

INVOICE_NO INVOICE_D
---------- ---------
1 16-JAN-08
1 16-FEB-08
3 16-JUL-08
5 18-AUG-08
6 21-AUG-08
7 31-AUG-08.

You might also like