list partitioning in oracle tables - oracle

I have created a table with default partitioning, Now I am adding another partition/subpartition then I am getting oracle error
CREATE TABLE STR_MAINFRAME_DB
(
CATEGORY VARCHAR(100) NOT NULL,
SUBCATEGORY VARCHAR(100) NOT NULL
)
PARTITION BY LIST (CATEGORY)
SUBPARTITION BY LIST (SUBCATEGORY)
(
PARTITION P_DUMMY VALUES (DEFAULT)
(
SUBPARTITION S_P_DUMMY VALUES (DEFAULT)
));
I am adding one more partition by using below SQL but it is throwing an error.
alter table str_mainframe_db add partition p_1 values ('A');
SQL Error: ORA-14323: cannot add partition when DEFAULT partition exists
14323. 00000 - "cannot add partition when DEFAULT partition exists"
*Cause: An ADD PARTITION operation cannot be executed when a partition
with DEFAULT values exists
Please help?????????

You cannot partition an existing table.
You will need to create a new, partitioned table and then move the data from the old table to the new. Then you can drop the old table and rename the new one to use the old table's name.
Depending on your downtime window and the nature of your application's access to data, you may want to use the dbms_redefinition package to manage this. It will like take more time than doing it manually but the overhead it imposes allows the old table to be kept online while the new table is being populated.

Related

Is it possible to automatically create a new partition in a list partitioned table?

The code below would create a new partition if I would insert a date that does not exist in my table. Is it possible to do the same thing in a list partitioned table, where the partition is based on a VARCHAR2 column?
ALTER TABLE MY_TABLE MODIFY
PARTITION BY RANGE(DATE) INTERVAL(NUMTODSINTERVAL(1,'day'))
( partition MY_PARTITION values less than (to_date('2019-06-01', 'yyyy-mm-dd')));
Yes, it is possible starting from the Oracle 12.2.
See the details here.

Oracle Automatic LIST partition using virtual column not allowing REFERENCE partition on child table

I’ve made an attempt to create partition on test table using virtual column. This approach is working good for PARENT or standalone tables. However, I cannot create REFERENCE partition on CHILD table if the PARENT table is PARTITIONED using virtual column. I get the following error on create table of CHILD table
ORA-14659: Partitioning method of the parent table is not supported
Oracle Version details:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
PL/SQL Release 12.2.0.1.0 - Production
Please find the script below.
--######################PARENT TABLE###########################################
DROP TABLE BILL_HEADER_TST;
CREATE TABLE BILL_HEADER_TST
(
BILL_HDR_SID NUMBER (30) NOT NULL,
TCN VARCHAR2 (21 BYTE) NOT NULL,
TCN_DATE DATE,
PROGRAM_CID NUMBER,
CONSTRAINT XPKBILL_HEADER_TST PRIMARY KEY (BILL_HDR_SID),
PARTN_KEY NUMBER
AS ( PROGRAM_CID
|| TO_NUMBER (TO_CHAR (TCN_DATE, 'YYYYMM')))
VIRTUAL
)
PARTITION BY LIST (PARTN_KEY) AUTOMATIC (PARTITION PDEFAULT VALUES (1201401));
------------------LOCAL INDEXES------------------------------------------------
CREATE INDEX XIE33BILL_HEADER_TST
ON BILL_HEADER_TST (TCN_DATE)
LOCAL;
CREATE INDEX XIE38BILL_HEADER_TST
ON BILL_HEADER_TST (PROGRAM_CID)
LOCAL;
---------------------INDEXES---------------------------------------------------
CREATE UNIQUE INDEX XAK1BILL_HEADER_TST
ON BILL_HEADER_TST (TCN)
LOGGING
NOPARALLEL;
--#############CHILD TABLE#####################################################
DROP TABLE BILL_LINE_TST;
CREATE TABLE BILL_LINE_TST
(
BILL_LINE_SID NUMBER (30) NOT NULL,
BILL_HDR_SID NUMBER (30) NOT NULL,
CLM_TYPE_CID NUMBER (3),
PROGRAM_CID NUMBER,
CONSTRAINT XPKBILL_LINE_TST PRIMARY KEY (BILL_LINE_SID),
CONSTRAINT XFK17_BILL_LINE_TST FOREIGN KEY
(BILL_HDR_SID)
REFERENCES BILL_HEADER_TST (BILL_HDR_SID) ON DELETE CASCADE
)
PARTITION BY REFERENCE (XFK17_BILL_LINE_TST)
ENABLE ROW MOVEMENT;
From the SQL Language manual
Automatic list partitioning is subject to the restrictions listed in "Restrictions on List Partitioning". The following additional restrictions apply:
An automatic list-partitioned table must have at least one partition
when created. Because new partitions are automatically created for
new, and unknown, partitioning key values, an automatic
list-partitioned table cannot have a DEFAULT partition.
Automatic list partitioning is not supported for index-organized
tables or external tables.
Automatic list partitioning is not supported for tables containing
varray columns.
You cannot create a local domain index on an automatic
list-partitioned table. You can create a global domain index on an
automatic list-partitioned table.
An automatic list-partitioned table cannot be a child table or a
parent table for reference partitioning.
Automatic list partitioning is not supported at the subpartition
level.

Move an Oracle table to being Index Organised

I have an Oracle table in a live production environment and the table is over half a gig in size. Is it possible to change this normal Oracle table from being heap organised to index organised or is this only achievable by moving the data from this table to another new table which is index organised? Either way, I would be grateful if you could you please list the steps involved in this procedure.
There is no way to alter a table to make it index-organized table. Instead you can redefine the table(using DBMS_REDEFINITION)or can create new table using CTAS.
Example:
create table t2 (
id number, first_name varchar2(20),
constraint pk_id primary key (id)
)
organization index
as select * from t1;
I never used DBMS_REDEFINITION but with CTAS it is not only step to create table if it is production.
List all indexes, constraints, foreign keys and so on based on system views
Prepare create index, constraints and alter foreign keys statements. prepare list of triggers, procedures that depend on table.
Create table as select (consider lock before that step if you can)
Create all indexes, constraints with prepared statements from step 2
Swap table names and swap foreign keys (this step may cause some errors if you hit insert on foreign keys (if you expect it on that time you should lock the table and tables referencing by foreign key).
Compile dependent objects from 2 (if you locked tables unlock here)
(if you haven't locked on step 3) Insert into table select * from new minus select * from old; or if you have timstamp of inserting row just insert new rows.
I hope the list is complete.

How do I alter my existing table to create a range partition in Oracle

I have existing table which has 10 years of data (I have taken dump).
I would like to Range partition the existing table on one date key column within the table.
Most of the examples I see are with CREATE TABLE..PARTITION BY RANGE... to add new partitions. But my table is existing table.
I assume I need some ALTER statement.
ALTER TABLE TABLE_NAME
PARTITION BY RANGE(CREATED_DATE)
PARTITION JAN16 VALUES LESS THAN (01-02-2016),
PARTITION FEB16 VALUES LESS THAN (01-03-2016) AND GREATER THAN(31-01-2016),//OR?
PARTITION MAR16 VALUES BETWEEN (01-03-2016) AND (31-03-2016), //OR?
Two questions..
Do I need Alter statement to add partitioning mechanism or need to work with create statement?
What is the proper syntax for keeping each partition having only ONE MONTH data.
If you are using Oracle 12c Release 2 you could use single ALTER to convert non-partitioned table to partitioned one (this is one way trip):
CREATE TABLE my_tab ( a NUMBER(38,0), b NUMBER(38,0));
ALTER TABLE MY_TAB MODIFY PARTITION BY RANGE (a) INTERVAL (1000) (
PARTITION p1 VALUES LESS THAN (1000)) ONLINE;
You could convert indexes too, adding:
update indexes (index_name [local/global]);
db<>fiddle demo
Beacuse your table non-partitioned you have two options:
Export data, drop table, create new patitioned table, import data.
Use split then exchange partition method. https://oracle-base.com/articles/misc/partitioning-an-existing-table-using-exchange-partition
Also, if you want new partition per month read about SET INTERVAL. For example:
CREATE TABLE tst
(col_date DATE)
PARTITION BY RANGE (col_date) INTERVAL (NUMTOYMINTERVAL(1, 'MONTH'))
(PARTITION col_date_min VALUES LESS THAN (TO_DATE('2010-01-01', 'YYYY-MM-DD')));

How to change RANGE value in PARTITIONS BY Range Oracle

I have an existing table within the next script:
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'))
);
What I need is to change the partition range to add an interval like this :
interval (numtoyminterval(1,'MONTH'))
I know that the right way to do it is when you create the table, but the table already exists and there are lot of records stored.
Is there any way to achieve this in Oracle 11g? I tried to ALTER the table but is not working due to 00940. 00000 - "invalid ALTER command"
Hope you can help me.
PS: I've been reading the whole documentation of Oracle in this two links without luck:
https://docs.oracle.com/cd/E17952_01/refman-5.5-en/alter-table-partition-operations.html
https://docs.oracle.com/cd/E17952_01/refman-5.1-en/partitioning-management-range-list.html
You can change a range partitioned table to a interval partitioned table with this command :
ALTER TABLE X SET INTERVAL(NUMTOYMINTERVAL(1, 'MONTH'));
You can change back to range partitioned table with this command :
ALTER TABLE X SET INTERVAL();
Interval partitioning is always a more preferable option to range partitioning if your partitions are always evenly created (in identical periods).
The commands are not resource intensive because you don't manipulate segments and data, you just tell Oracle to begin or stop creating new partitions if new data that is inserted in the table doesn't fit by partition key in any existing partition.

Resources