Possible to modify an existing partitioned Oracle table to utilize INTERVAL? [duplicate] - oracle

I have a table which is partitioned as below and has millions of rows of data. Table size is 120 GB.
PARTITION BY RANGE (Read_time) INTERVAL(NUMTOYMINTERVAL(1, 'MONTH'))
Now I want to change to this partitioning strategy with existing data and future data. Table is inserted daily by job.
PARTITION BY RANGE (Read_time) INTERVAL(NUMTODSINTERVAL(1, 'DAY'))
I have 12 month partition (Oct'18 to Nov'19). I want partition to be converted to daywise.
For example: For Jul'19 partition, it should to be splitted to
01 Jul'19,
02 Jul'19
.......
31 Jul'19.
Data should also be moved to new partition
I tried split partition. New partition got created day wise , but rows didn't move to new partition.

To change for monthly interval to daily is a simple as
ALTER TABLE test SET INTERVAL (NUMTODSINTERVAL(1,'DAY'));
see the documentation for further details
Lets illustrate in on a small example
create table test
(dt date)
PARTITION BY RANGE (dt)
INTERVAL (NUMTOYMINTERVAL(1,'MONTH'))
(
PARTITION part_01 values LESS THAN (TO_DATE('01-01-2019','DD-MM-YYYY'))
);
insert into test (dt)
select date'2019-01-01' + rownum dt from dual
connect by level <= 100;
The table in montly intrval partitioned and contains 100 days of data - yielding in one initial partition and 4 new montly partition.
PARTITION_NAME HIGH_VALUE
------------------------------ --------------------------------------------------------------------------------
PART_01 TO_DATE(' 2019-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93334 TO_DATE(' 2019-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93335 TO_DATE(' 2019-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93336 TO_DATE(' 2019-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93337 TO_DATE(' 2019-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
Now we switch to daily partitioning
ALTER TABLE test SET INTERVAL (NUMTODSINTERVAL(1,'DAY'));
This makes nothing with existing data (so it is instant operation), also the new data for the current month will go in the current (month) partition.
The data loaded for the new month will be partitioned on daily basis.
Lets insert few new days
insert into test (dt)
select date'2019-01-01' + 100 +rownum dt from dual
connect by level <= 22;
PARTITION_NAME HIGH_VALUE
------------------------------ --------------------------------------------------------------------------------
PART_01 TO_DATE(' 2019-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93334 TO_DATE(' 2019-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93335 TO_DATE(' 2019-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93336 TO_DATE(' 2019-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93337 TO_DATE(' 2019-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93338 TO_DATE(' 2019-05-02 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93339 TO_DATE(' 2019-05-03 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93340 TO_DATE(' 2019-05-04 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
As expected starting with May the data are daily partitioned.
If you need also to re-partitioned your historical data, this will require reorganisation (data movement - will take some time for 120GB) using split partition.
alter table test
SPLIT PARTITION FOR(TO_DATE('2019-02-01','yyyy-mm-dd'))
AT (TO_DATE('2019-02-27','yyyy-mm-dd'));
alter table test
SPLIT PARTITION FOR(TO_DATE('2019-02-01','yyyy-mm-dd'))
AT (TO_DATE('2019-02-26','yyyy-mm-dd'));
This splits the last day in a new partition, you'll have to do it for each day in each monthly partition.
After this step also the history data is partitioned per day:
select * from test partition for ( DATE'2019-02-26');
DT
-------------------
26.02.2019 00:00:00

Related

How to move data from partitioned table to another partitioned table

I have two monthly interval partitioned tables table1 and table2. Table1 is history table which holds historic data and table2 holds latest/live 6 months data. Every month I need to add or move the oldest partition from table2 to the history table table1.
Here is how to do it with no movement of data, just dictionary operations as Hermann has suggested.
T1 is my current 6 months, and T2 is history
SQL> create table t1
2 partition by range (x)
3 interval ( numtoyminterval(1,'MONTH') )
4 ( partition p1 values less than ( date '2021-01-01') )
5 as
6 select date '2021-01-01'+rownum x,
7 rownum y
8 from dual
9 connect by level <= 180;
Table created.
SQL>
SQL> create table t2
2 partition by range (x)
3 interval ( numtoyminterval(1,'MONTH') )
4 ( partition p1 values less than ( date '2015-01-01') )
5 as
6 select date '2021-01-01'-rownum x,
7 rownum y
8 from dual
9 connect by level <= 1000;
Table created.
SQL>
SQL> select partition_name, high_value
2 from user_tab_partitions
3 where table_name = 'T1';
PARTITION_NAME HIGH_VALUE
------------------------------ --------------------------------------------------------------------------------
P1 TO_DATE(' 2021-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22038 TO_DATE(' 2021-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22039 TO_DATE(' 2021-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22040 TO_DATE(' 2021-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22041 TO_DATE(' 2021-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22042 TO_DATE(' 2021-06-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22043 TO_DATE(' 2021-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
7 rows selected.
SQL>
SQL> select partition_name, high_value
2 from user_tab_partitions
3 where table_name = 'T2';
PARTITION_NAME HIGH_VALUE
------------------------------ --------------------------------------------------------------------------------
P1 TO_DATE(' 2015-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22044 TO_DATE(' 2021-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22045 TO_DATE(' 2020-12-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22046 TO_DATE(' 2020-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22047 TO_DATE(' 2020-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22048 TO_DATE(' 2020-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22049 TO_DATE(' 2020-08-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22050 TO_DATE(' 2020-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22051 TO_DATE(' 2020-06-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22052 TO_DATE(' 2020-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22053 TO_DATE(' 2020-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22054 TO_DATE(' 2020-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22055 TO_DATE(' 2020-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22056 TO_DATE(' 2020-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22057 TO_DATE(' 2019-12-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22058 TO_DATE(' 2019-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22059 TO_DATE(' 2019-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22060 TO_DATE(' 2019-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22061 TO_DATE(' 2019-08-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22062 TO_DATE(' 2019-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22063 TO_DATE(' 2019-06-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22064 TO_DATE(' 2019-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22065 TO_DATE(' 2019-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22066 TO_DATE(' 2019-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22067 TO_DATE(' 2019-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22068 TO_DATE(' 2019-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22069 TO_DATE(' 2018-12-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22070 TO_DATE(' 2018-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22071 TO_DATE(' 2018-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22072 TO_DATE(' 2018-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22073 TO_DATE(' 2018-08-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22074 TO_DATE(' 2018-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22075 TO_DATE(' 2018-06-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22076 TO_DATE(' 2018-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
34 rows selected.
To do a table exchange, you need to create a template table first, ie, you need something to exchange with
SQL>
SQL> create table exc
2 for exchange with table t1;
Table created.
Now I take the partition I want to remove from T1, and exchange it with EXC
SQL>
SQL> alter table t1 exchange partition for ( date '2021-01-15' ) with table exc;
Table altered.
Now I want to exchange it "into" T2, but I need a partition in T2 into which I can do the exchange. That partition does not exist yet, because it doesn't contain any of the 6 months in the current data. Thus we need to create an empty one. A simple trick to do that is the lock the non-existent partition, which will have the effect of creating one.
SQL>
SQL> lock table t2 partition for ( date '2021-01-15' ) in exclusive mode;
Table(s) Locked.
SQL>
SQL> select partition_name, high_value
2 from user_tab_partitions
3 where table_name = 'T2';
PARTITION_NAME HIGH_VALUE
------------------------------ --------------------------------------------------------------------------------
P1 TO_DATE(' 2015-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22044 TO_DATE(' 2021-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22045 TO_DATE(' 2020-12-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22046 TO_DATE(' 2020-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22047 TO_DATE(' 2020-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22048 TO_DATE(' 2020-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22049 TO_DATE(' 2020-08-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22050 TO_DATE(' 2020-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22051 TO_DATE(' 2020-06-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22052 TO_DATE(' 2020-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22053 TO_DATE(' 2020-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22054 TO_DATE(' 2020-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22055 TO_DATE(' 2020-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22056 TO_DATE(' 2020-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22057 TO_DATE(' 2019-12-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22058 TO_DATE(' 2019-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22059 TO_DATE(' 2019-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22060 TO_DATE(' 2019-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22061 TO_DATE(' 2019-08-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22062 TO_DATE(' 2019-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22063 TO_DATE(' 2019-06-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22064 TO_DATE(' 2019-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22065 TO_DATE(' 2019-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22066 TO_DATE(' 2019-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22067 TO_DATE(' 2019-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22068 TO_DATE(' 2019-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22069 TO_DATE(' 2018-12-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22070 TO_DATE(' 2018-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22071 TO_DATE(' 2018-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22072 TO_DATE(' 2018-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22073 TO_DATE(' 2018-08-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22074 TO_DATE(' 2018-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22075 TO_DATE(' 2018-06-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22076 TO_DATE(' 2018-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22077 TO_DATE(' 2021-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
35 rows selected.
Notice that we gained a new partition (which is empty). Now I exchange the EXC table (which has 1 month of data) with the empty partition.
SQL>
SQL> alter table t2 exchange partition for ( date '2021-01-15' ) with table exc;
Table altered.
SQL>
and we are done. Notice that we never needed to reference any of the interval partitions by name, we just used the FOR option in order to avoid that.

Can i change range interval partition from month to day in oracle

I have a table which is partitioned as below and has millions of rows of data. Table size is 120 GB.
PARTITION BY RANGE (Read_time) INTERVAL(NUMTOYMINTERVAL(1, 'MONTH'))
Now I want to change to this partitioning strategy with existing data and future data. Table is inserted daily by job.
PARTITION BY RANGE (Read_time) INTERVAL(NUMTODSINTERVAL(1, 'DAY'))
I have 12 month partition (Oct'18 to Nov'19). I want partition to be converted to daywise.
For example: For Jul'19 partition, it should to be splitted to
01 Jul'19,
02 Jul'19
.......
31 Jul'19.
Data should also be moved to new partition
I tried split partition. New partition got created day wise , but rows didn't move to new partition.
To change for monthly interval to daily is a simple as
ALTER TABLE test SET INTERVAL (NUMTODSINTERVAL(1,'DAY'));
see the documentation for further details
Lets illustrate in on a small example
create table test
(dt date)
PARTITION BY RANGE (dt)
INTERVAL (NUMTOYMINTERVAL(1,'MONTH'))
(
PARTITION part_01 values LESS THAN (TO_DATE('01-01-2019','DD-MM-YYYY'))
);
insert into test (dt)
select date'2019-01-01' + rownum dt from dual
connect by level <= 100;
The table in montly intrval partitioned and contains 100 days of data - yielding in one initial partition and 4 new montly partition.
PARTITION_NAME HIGH_VALUE
------------------------------ --------------------------------------------------------------------------------
PART_01 TO_DATE(' 2019-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93334 TO_DATE(' 2019-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93335 TO_DATE(' 2019-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93336 TO_DATE(' 2019-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93337 TO_DATE(' 2019-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
Now we switch to daily partitioning
ALTER TABLE test SET INTERVAL (NUMTODSINTERVAL(1,'DAY'));
This makes nothing with existing data (so it is instant operation), also the new data for the current month will go in the current (month) partition.
The data loaded for the new month will be partitioned on daily basis.
Lets insert few new days
insert into test (dt)
select date'2019-01-01' + 100 +rownum dt from dual
connect by level <= 22;
PARTITION_NAME HIGH_VALUE
------------------------------ --------------------------------------------------------------------------------
PART_01 TO_DATE(' 2019-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93334 TO_DATE(' 2019-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93335 TO_DATE(' 2019-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93336 TO_DATE(' 2019-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93337 TO_DATE(' 2019-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93338 TO_DATE(' 2019-05-02 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93339 TO_DATE(' 2019-05-03 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93340 TO_DATE(' 2019-05-04 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
As expected starting with May the data are daily partitioned.
If you need also to re-partitioned your historical data, this will require reorganisation (data movement - will take some time for 120GB) using split partition.
alter table test
SPLIT PARTITION FOR(TO_DATE('2019-02-01','yyyy-mm-dd'))
AT (TO_DATE('2019-02-27','yyyy-mm-dd'));
alter table test
SPLIT PARTITION FOR(TO_DATE('2019-02-01','yyyy-mm-dd'))
AT (TO_DATE('2019-02-26','yyyy-mm-dd'));
This splits the last day in a new partition, you'll have to do it for each day in each monthly partition.
After this step also the history data is partitioned per day:
select * from test partition for ( DATE'2019-02-26');
DT
-------------------
26.02.2019 00:00:00

Query joined partitioned tables

I have 2 partitioned tables . I want to left joined them it means that i want all record of table 'A' that is in specific date , and data in table 'B' if there is any matched record (also in specific date). both tables are partitioned so i use partitioned column (time) in where clause , but in this query when there is not any matched record in table 'B' , the condition 'B.time' become null and the records of table 'A' dose not appear in result.
if I do not use time condition for table 'B', the execution plan of it become partition range all and has bad performance .
how can i edit the query?
select * from A left outer join B SSRESP
on A.ID = B.A_ID where
A.time >= to_date('1396/09/26 00:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')
and A.time <= to_date('1396/10/27 11:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')
and B.time >=
to_date('1396/09/26 00:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')
and B.time <=
to_date('1396/10/27 11:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')
There are 2 possibilities.
1) Move the condition to the on-clause:
select *
from A
left outer join B
on A.ID = B.A_ID
and B.time >= to_date('1396/09/26 00:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')
and B.time <= to_date('1396/10/27 11:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')
where A.time >= to_date('1396/09/26 00:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')
and A.time <= to_date('1396/10/27 11:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')
2) Filter the table before the left join:
select *
from A
left outer join
(SELECT * FROM B
WHERE B.time >= to_date('1396/09/26 00:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')
and B.time <= to_date('1396/10/27 11:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')) AS B
on A.ID = B.A_ID
where A.time >= to_date('1396/09/26 00:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')
and A.time <= to_date('1396/10/27 11:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')

Change the range of existing partition

I have a table with two partitions:
create table MY
(
id NUMBER not null,
dat DATE
)
partition by range (dat)
(
partition PART_ARCHIVE values less than (TO_DATE(' 2015-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
tablespace ARCHIVE,
partition PART_ACTUAL values less than (MAXVALUE) tablespace ACTUAL
);
Can I change the PART_ARCHIVE partition date interval without recreating table?
I need to set that:
partition PART_ARCHIVE values less than (TO_DATE(' 2017-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
I don't know whether you can do it in a single command but this one should work:
ALTER TABLE MY SPLIT PARTITION PART_ACTUAL INTO
(PARTITION PART_2017 VALUES LESS THAN (DATE '2017-01-01'),
PARTITION PART_ACTUAL);
ALTER TABLE MY MERGE PARTITIONS PART_2017, PART_ARCHIVE INTO PART_ARCHIVE;

Dynamic table partitioning in Oracle

I'm in the process of building a database storage for my app consisting on a single table with a huge data volume (hundreds of millions of records). I'm planning on having an index on the date field, since I'll be doing a batch recovery of all the records in a given period of time every now and then (for example, retrieving all records for the following day, at midnight).
Since the number of records is huge and performance is an important concern in this system, I would like to know if there is a way I can dynamically partition my table so that I can retrieve the records faster, creating and truncating partitions as they are no longer needed. For example, how would I go about creating a partition for the following day and populating it with the rest of the data after I'm done processing today's records?
In 11g we can define INTERVAL partitions, and Oracle will automatically create new partitions when it gets new records whose keys don't fit in any of the existing ranges. This is a very cool feature. Find out more.
One thing to bear in mind is that Partitioning is a chargeable extra on top of the Enterprise Edition license. So it is not cheap to use.
you can automate the process of creating or truncating partitions through the use of dynamic SQL. You would write procedures with either EXECUTE IMMEDIATE or DBMS_SQL and you would schedule them with DBMS_JOB or DBMS_SCHEDULER (DBMS_SCHEDULER is a 10g feature and is more versatile than DBMS_JOB).
You probably want to build the partition statements manually first and automate the process later when you are confident with the DDL. You will find all the synthax in the documentation for the ALTER TABLE statement.
Here is a sample of something I came up with for creating partitions using SYSDATE and an offset. I had to create replacement parameters with a string concatenated to the SYSDATE:
COLUMN temp_var new_value partition_name_01;
SELECT 'TABLE_NAME_' || TO_CHAR(SYSDATE - 3, 'YYYYMMDD') AS temp_var FROM dual;
COLUMN temp_var new_value partition_date_01;
SELECT TO_CHAR(SYSDATE - 3, 'SYYYY-MM-DD') || ' 00:00:00' AS temp_var FROM dual;
COLUMN temp_var new_value partition_name_02;
SELECT 'TABLE_NAME_' || TO_CHAR(SYSDATE - 2, 'YYYYMMDD') AS temp_var FROM dual;
COLUMN temp_var new_value partition_date_02;
SELECT TO_CHAR(SYSDATE - 2, 'SYYYY-MM-DD') || ' 00:00:00' AS temp_var FROM dual;
COLUMN temp_var new_value partition_name_03;
SELECT 'TABLE_NAME_' || TO_CHAR(SYSDATE - 1, 'YYYYMMDD') AS temp_var FROM dual;
COLUMN temp_var new_value partition_date_03;
SELECT TO_CHAR(SYSDATE - 1, 'SYYYY-MM-DD') || ' 00:00:00' AS temp_var FROM dual;
COLUMN temp_var new_value partition_name_04;
SELECT 'TABLE_NAME_' || TO_CHAR(SYSDATE, 'YYYYMMDD') AS temp_var FROM dual;
COLUMN temp_var new_value partition_date_04;
SELECT TO_CHAR(SYSDATE, 'SYYYY-MM-DD') || ' 00:00:00' AS temp_var FROM dual;
CREATE TABLE TABLE_NAME
(
SEQ_NO NUMBER NOT NULL,
INSERT_DATE DATE NOT NULL,
FIRST_NAME VARCHAR2 (256 BYTE),
LAST_NAME VARCHAR2 (256 BYTE),
ID_NUM NUMBER,
ID_STATUS NUMBER
)
PARTITION BY RANGE
(INSERT_DATE)
SUBPARTITION BY LIST
(ID_STATUS)
SUBPARTITION TEMPLATE (
SUBPARTITION SP1 VALUES (0) TABLESPACE &tblspce,
SUBPARTITION SP2 VALUES (1) TABLESPACE &tblspce,
SUBPARTITION SP3 VALUES (2) TABLESPACE &tblspce)
(
PARTITION &partition_name_01
VALUES LESS THAN
(TO_DATE ('&partition_date_01',
'SYYYY-MM-DD HH24:MI:SS',
'NLS_CALENDAR=GREGORIAN')),
PARTITION &partition_name_02
VALUES LESS THAN
(TO_DATE ('&partition_date_02',
'SYYYY-MM-DD HH24:MI:SS',
'NLS_CALENDAR=GREGORIAN')),
PARTITION &partition_name_03
VALUES LESS THAN
(TO_DATE ('&partition_date_03',
'SYYYY-MM-DD HH24:MI:SS',
'NLS_CALENDAR=GREGORIAN')),
sysdate
PARTITION &partition_name_04
VALUES LESS THAN
(TO_DATE ('&partition_date_04',
'SYYYY-MM-DD HH24:MI:SS',
'NLS_CALENDAR=GREGORIAN')))
ENABLE ROW MOVEMENT;
There's a product that takes care of it automatically. PartitionManager for Oracle provides automatic partition management, based on the organization retention, including purging and archiving old data, statistics copy etc. You can try it out at http://www.xyrosoft.com

Resources