Oracle Merge Partition (based on partition values) - oracle

I would like to run a procedure that merges table partitions that match a certain criteria.
As example - table1 is range partitions by date and has 5 partitions.
Partitions = empire1, empire2, rebels1, rebels2, yoda1.
Table DESC:
INVOICE_NO NOT NULL NUMBER
INVOICE_DATE NOT NULL DATE
COMMENTS VARCHAR2(500)
it is partitioned by INVOICE_DATE as follows
PARTITION REBELS1 VALUES LESS THAN (TO_DATE('01-JAN-2014','DD-MON-YYYY')),
PARTITION REBELS2 VALUES LESS THAN (TO_DATE('01-JAN-2015','DD-MON-YYYY')),
PARTITION EMPIRE1 VALUES LESS THAN (TO_DATE('01-JAN-2016','DD-MON-YYYY')),
PARTITION EMPIRE2 VALUES LESS THAN (TO_DATE('01-JAN-2017','DD-MON-YYYY')),
PARTITION YODA VALUES LESS THAN (TO_DATE('01-JAN-2018','DD-MON-YYYY')),
I need to grab all partitions named rebel% and yoda% and merge them into one new partition called 'jawa'.
In the end only 3 partitions would exist, empire1, empire2 and jawa.

Related

partition in oracle

CREATE TABLE temp_stud as select * from STUD_MAST
PARTITION BY RANGE(ADM_DT)
(
PARTITION temp_stud1 VALUES LESS THAN(TO_DATE('02/01/2000','MM/DD/YYYY')),
PARTITION temp_stud2 VALUES LESS THAN(TO_DATE('03/01/2000','MM/DD/YYYY')),
PARTITION temp_stud3 VALUES LESS THAN(TO_DATE('04/01/2000','MM/DD/YYYY')),
PARTITION temp_stud4 VALUES LESS THAN(TO_DATE('05/01/2000','MM/DD/YYYY'))
);
I am getting a missing left parenthesis error for above table creation can anyone tell me what is the issue in above creation
Note: ADM_DT is a date column with data type char(8) and storing format YYMMDD
Please use below SQL. The Creation of Partition has be part of Create table.
CREATE TABLE temp_stud
PARTITION BY RANGE(ADM_DT)
(
PARTITION temp_stud1 VALUES LESS THAN(TO_DATE('02/01/2000','MM/DD/YYYY')),
PARTITION temp_stud2 VALUES LESS THAN(TO_DATE('03/01/2000','MM/DD/YYYY')),
PARTITION temp_stud3 VALUES LESS THAN(TO_DATE('04/01/2000','MM/DD/YYYY')),
PARTITION temp_stud4 VALUES LESS THAN(TO_DATE('05/01/2000','MM/DD/YYYY'))
)
as select * from STUD_MAST;

Divide into hourly partition #2

I've asked a similar question before but couldn't figure it out(Divide into hourly partitions and inset data by partitions).
I created a table with hourly partitions, and when inserting data, it correctly divides by hourly partitions:
create table SOFT_CALLS(
callid VARCHAR2(90),
start_time date not null,
start_time_h as (to_char(start_time, 'HH24')),
duration NUMBER,
first_question VARCHAR2(4000),
second_question VARCHAR2(4000),
client_id VARCHAR2(20),
contract_id VARCHAR2(20),
client_dwh_id VARCHAR2(20)
)
partition by list (start_time_h)
(
partition p_08 values ('08'),
partition p_09 values ('09'),
partition p_10 values ('10'),
partition p_11 values ('11'),
partition p_12 values ('12'),
partition p_13 values ('13'),
partition p_14 values ('14'),
partition p_15 values ('15'),
partition p_16 values ('16'),
partition p_17 values ('17'),
partition p_18 values ('18'),
partition p_19 values ('19'),
partition p_20 values ('20'),
partition p_21 values ('21'),
partition p_22 values ('22'),
partition p_23 values ('23')
);
The logic of the procedure should be as follows: so that it inserts data into the table for trunc(sysdate - 1/24, 'hh') and trunc(sysdate + 1/24, 'hh') and then transfers the same data to SAS and at the end simply drop these partitions so that the procedure does not do this for the entire trunc (sysdate) every five minutes, so resource consumption will decrease.
It is necessary that the table stores data in hourly partitions, that is, it will not truncate all the data each time and refill for the whole day, but only drop partitions for the last hour and also insert data without losing data for the hours that have already passed.
But the problem is that list partitions cannot be dropped during this period trunc(sysdate - 1/24, 'hh') and trunc(sysdate + 1/24, 'hh').
What other examples are there for dividing a table into hourly partitions and so that in the end there would be no problems dropping them over the period that I indicated? I've looked all over the internet, but I haven't been able to find any specific information.

How to split existing partitions

I have multiple partitions on my table as below.
Partition- Day_20190509 with high value of 20190510
Partition- Day_20190520 with high value of 20190521
Partition- Day_99999999 with MAXVALUE as high.
I want to create three new partitions for Day_20190510,Day_20190513,Day_20190514 with high values as 20190513,20190514,20190520 respectively.
I believe this can done using SPLIT partitions but could not understand how I can create partitions in between. Can someone assist with the query for this?
I tried using partition split option but could not understand what will be my range part and new partitions
ALTER TABLE table_name SPLIT PARTITION partition_name
AT (range_part_value)
INTO
(
PARTITION new_part1
[TABLESPACE tablespace_name],
PARTITION new_part2
[TABLESPACE tablespace_name]
);
Values you described as high values (20190513,20190514,20190520) in new partitions (Day_20190510,Day_20190513,Day_20190514) belong to the current partition: Day_20190520 (Value range: 20190511 - 20190521)
So current partition Day_20190520 must be split as follows:
ALTER TABLE table_name SPLIT PARTITION Day_20190520 INTO
(PARTITION Day_20190510 VALUES LESS THAN (20190514), -- 20190513 + 1
PARTITION Day_20190513 VALUES LESS THAN (20190515), -- 20190514 + 1
PARTITION Day_20190514 VALUES LESS THAN (20190521), -- 20190520 + 1
PARTITION Day_20190520_1);
Hope this will solve your problem.

How to create monthly partition in oracle?

I have a table with 2017 and 2018 year data. Need to create monthly partition on that table.
So I created one non partitioned table and loaded all the data from original table. now I am converting the new table to a monthly partitioned table.
When I am altering getting error as
ORA-14300: partitioning key maps to a partition outside maximum
permitted number of partitions
My Script is
ALTER TABLE ORDERHDR_PART MODIFY
PARTITION BY RANGE (LASTUPDATE) INTERVAL(NUMTOYMINTERVAL(1, 'MONTH'))
(
PARTITION ORDERHDR_PART_JAN VALUES less than (TO_DATE('01-02-2018','DD-MM-YYYY')),
PARTITION ORDERHDR_PART_FEB VALUES less than (TO_DATE('01-03-2018','DD-MM-YYYY')),
PARTITION ORDERHDR_PART_MAR VALUES less than (TO_DATE('01-04-2018','DD-MM-YYYY')),
PARTITION ORDERHDR_PART_APR VALUES less than (TO_DATE('01-05-2018','DD-MM-YYYY')),
PARTITION ORDERHDR_PART_MAY VALUES less than (TO_DATE('01-06-2018','DD-MM-YYYY')),
PARTITION ORDERHDR_PART_JUN VALUES less than (TO_DATE('01-07-2018','DD-MM-YYYY')),
PARTITION ORDERHDR_PART_JUL VALUES less than (TO_DATE('01-08-2018','DD-MM-YYYY')),
PARTITION ORDERHDR_PART_AUG VALUES less than (TO_DATE('01-09-2018','DD-MM-YYYY')),
PARTITION ORDERHDR_PART_SEP VALUES less than (TO_DATE('01-10-2018','DD-MM-YYYY')),
PARTITION ORDERHDR_PART_OCT VALUES less than (TO_DATE('01-11-2018','DD-MM-YYYY')),
PARTITION ORDERHDR_PART_NOV VALUES less than (TO_DATE('01-12-2018','DD-MM-YYYY')),
PARTITION ORDERHDR_PART_DEC VALUES less than (TO_DATE('01-01-2019','DD-MM-YYYY'))
)ONLINE;
I think your approach is wrong.
First create a partitioned table, e.g.
CREATE TABLE ORDERHDR_PART (....)
PARTITION BY RANGE (LASTUPDATE) INTERVAL (NUMTOYMINTERVAL(1, 'MONTH'))
(
PARTITION ORDERHDR_INITIAL VALUES less than (DATE '2000-01-01')
);
Then transfer existing data to the new table.
Either you use a simple INSERT INTO ORDERHDR_PART SELECT * FROM ORDERHDR_2017;
Oracle will create monthly partitions automatically based on LASTUPDATE value.
With this methods you would duplicate (temporary) your data and/or you may face a performance issue.
The other method is to use Exchanging Partitions, should be like this
ALTER TABLE ORDERHDR_PART
EXCHANGE PARTITION FOR (DATE '2017-01-01')
WITH TABLE ORDERHDR_2017
INCLUDING INDEXES;
I don't know whether "PARTITION FOR (DATE '2017-01-01')" is created automatically, perhaps you have to run INSERT INTO ORDERHDR_PART (LASTUPDATE) VALUES (DATE '2017-01-01'); ROLLBACK; in order to create it first.
You will get one partition for all months, afterwards you can split the partition with Splitting into Multiple Partitions. Should be like this:
ALTER TABLE ORDERHDR_PART SPLIT PARTITION FOR (DATE '2017-01-01') INTO (
PARTITION ORDERHDR_PART_JAN VALUES less than (TO_DATE('01-02-2018','DD-MM-YYYY')),
PARTITION ORDERHDR_PART_FEB VALUES less than (TO_DATE('01-03-2018','DD-MM-YYYY')),
PARTITION ORDERHDR_PART_MAR VALUES less than (TO_DATE('01-04-2018','DD-MM-YYYY')),
PARTITION ORDERHDR_PART_APR VALUES less than (TO_DATE('01-05-2018','DD-MM-YYYY')),
PARTITION ORDERHDR_PART_MAY VALUES less than (TO_DATE('01-06-2018','DD-MM-YYYY')),
PARTITION ORDERHDR_PART_JUN VALUES less than (TO_DATE('01-07-2018','DD-MM-YYYY')),
PARTITION ORDERHDR_PART_JUL VALUES less than (TO_DATE('01-08-2018','DD-MM-YYYY')),
PARTITION ORDERHDR_PART_AUG VALUES less than (TO_DATE('01-09-2018','DD-MM-YYYY')),
PARTITION ORDERHDR_PART_SEP VALUES less than (TO_DATE('01-10-2018','DD-MM-YYYY')),
PARTITION ORDERHDR_PART_OCT VALUES less than (TO_DATE('01-11-2018','DD-MM-YYYY')),
PARTITION ORDERHDR_PART_NOV VALUES less than (TO_DATE('01-12-2018','DD-MM-YYYY')),
PARTITION ORDERHDR_PART_DEC VALUES less than (TO_DATE('01-01-2019','DD-MM-YYYY'))
);
Note, by default you cannot drop the inital partition of a RANGE partitioned table. If you face this problem execute:
ALTER TABLE ORDERHDR_PART SET INTERVAL ();
ALTER TABLE ORDERHDR_PART DROP PARTITION ORDERHDR_INITIAL;
ALTER TABLE ORDERHDR_PART SET INTERVAL (NUMTOYMINTERVAL(1, 'MONTH'));

Partitioning a table with one value in one partition and the rest in another partition

For example, I have a table name Emp and it has empname, designation, salary as columns. I would like this table to have 2 partitions, like list of employees who are managers in one partition and rest(engineer, peon, clerk) in one partition.
can someone help on how to create it
In this case you will have to use LIST based partition. Create a pertition where ROLE = MANAGER and create another partition which is default. Here is an example which will help you.
Exclude values from oracle partition
Example
CREATE TABLE EMPLOYEE (EMP_ID VARCHAR2(25),
EMP_NAME VARCHAR2(250),
ROLE VARCHAR2(100)
)
PARTITION BY LIST (ROLE)
(
PARTITION part_managers
VALUES ('MANAGER'),
PARTITION part_others
VALUES (DEFAULT)
);
Please refer the following URL and example:
For example, the following SQL statement splits the sales_Q4_2007 partition of the partitioned by range table sales splits into five partitions corresponding to the quarters of the next year. In this example, the partition sales_Q4_2008 implicitly becomes the high bound of the split partition.
ALTER TABLE sales SPLIT PARTITION sales_Q4_2007 INTO
( PARTITION sales_Q4_2007 VALUES LESS THAN (TO_DATE('01-JAN-2008','dd-MON-yyyy')),
PARTITION sales_Q1_2008 VALUES LESS THAN (TO_DATE('01-APR-2008','dd-MON-yyyy')),
PARTITION sales_Q2_2008 VALUES LESS THAN (TO_DATE('01-JUL-2008','dd-MON-yyyy')),
PARTITION sales_Q3_2008 VALUES LESS THAN (TO_DATE('01-OCT-2008','dd-MON-yyyy')),
PARTITION sales_Q4_2008);
For the sample table customers partitioned by list, the following statement splits the partition Europe into three partitions.
ALTER TABLE list_customers SPLIT PARTITION Europe INTO
(PARTITION western-europe VALUES ('GERMANY', 'FRANCE'),
PARTITION southern-europe VALUES ('ITALY'),
PARTITION rest-europe);
https://docs.oracle.com/database/121/VLDBG/GUID-01C14320-0D7B-48BE-A5AD-003DDA761277.htm
You will get some idea about this.

Resources