Best way to get high value of partition from oracle database?
"Best" is subjective but you can retrieve the high values by quering the data dictionary:
SELECT partition_name,
high_value
FROM USER_TAB_PARTITIONS
WHERE table_name = 'YOUR_TABLE_NAME';
One way is to use XML
create table t (
x date
) partition by range (x) (
partition p0 values less than (date'2015-01-01'),
partition p1 values less than (date'2015-06-01'),
partition pmax values less than (maxvalue)
);
with xml as (
select dbms_xmlgen.getxmltype('select table_name, partition_name, high_value from user_tab_partitions where table_name = ''T''') as x
from dual
)
select extractValue(rws.object_value, '/ROW/TABLE_NAME') table_name,
extractValue(rws.object_value, '/ROW/PARTITION_NAME') partition,
extractValue(rws.object_value, '/ROW/HIGH_VALUE') high_value
from xml x,
table(xmlsequence(extract(x.x, '/ROWSET/ROW'))) rws;
TABLE_NAME PARTITION HIGH_VALUE
---------- ---------- ------------------------------------------------------------------------------------------
T P0 TO_DATE(' 2015-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')
T P1 TO_DATE(' 2015-06-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')
T PMAX MAXVALUE
Related
create table TEST_TABLE_2
(
report_month DATE,
name varchar(128)
)
partition by list (REPORT_MONTH)
(
partition TEST_PART_2022_05_31 values (TO_DATE(' 2022-05-31 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
tablespace TEST_TABLESPACE,
partition MONTH_UNKNOWN values (default)
tablespace TEST_TABLESPACE
);
create table TEST_TABLE_1
(
report_month DATE,
name varchar(128)
)
partition by list (REPORT_MONTH)
(
partition TEST_PART_2022_05_31 values (TO_DATE(' 2022-05-31 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
tablespace TEST_TABLESPACE,
partition MONTH_UNKNOWN values (default)
tablespace TEST_TABLESPACE
);
Advise me please, How I can to exchange partition TEST_PART_2022_05_31 from TEST_TABLE_2 with partition TEST_PART_2022_05_31 in TEST_TABLE_1?
WHen I exec this script
ALTER TABLE ADS.test_table_1
EXCHANGE PARTITION TEST_PART_2022_05_31
WITH TABLE ADS.test_table_2
I get Error: ORA-14095: ALTER TABLE EXCHANGE requires a non-partitioned, non-clustered table
Are you looking for something like this?
create table t (
c1, c2, c3
) partition by range ( c2 )
interval ( interval '1' month ) (
partition p0 values less than ( date'2022-02-01' )
)
as
select level, date'2022-01-01' + level, 'remove'
from dual
connect by level <= 100;
create table temp
for exchange with table t;
select count(*) from temp;
0
alter table t
exchange partition p0
with table temp;
select count(*) from temp;
100
I have the following table :
CREATE TABLE "ICTPART_DAILY_SUMMARY"
(
"EVENT_START_DATE" DATE
"ACCOUNTING_METHOD" CHAR(1),
......etc
)
PARTITION BY RANGE ("EVENT_START_DATE")
(PARTITION "ICTPART_DAY_SUM_P20220218" VALUES LESS THAN (TO_DATE(' 2022-02-19 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
NOCOMPRESS LOGGING
TABLESPACE "TBS_ICTQUO_D" ,
PARTITION "ICTPART_DAY_SUM_P20220219" VALUES LESS THAN (TO_DATE(' 2022-02-20 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
NOCOMPRESS LOGGING
TABLESPACE "TBS_ICTQUO_D" ,
PARTITION "ICTPART_DAY_SUM_PMAX" VALUES LESS THAN (MAXVALUE)
NOCOMPRESS LOGGING
TABLESPACE "TBS_ICTQUO_D" ) ;
This table is being partitioned everyday as you can see by an old ksh script.
i want to continue the same work with an sql script who run every first of the month and alter that table and do the same daily partition for 30 days.
for exemple : we are in 01/03/2022, i want to added partition for 01/03/2022 , 02/03/2022, 03/03/2022 ..... etc until 31/03/2022
that sql script will be putted in a ETL who run every first of the month and do that partition
Why not get rid of the ksh script and use INTERVAL PARTITIONs. This way a new PARTITION will be automatically created when a new day is inserted in the table.
CREATE TABLE t1 (
seq_num NUMBER GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL,
dt DATE
)
PARTITION BY RANGE (dt)
INTERVAL (NUMTODSINTERVAL(1,'DAY'))
(
PARTITION OLD_DATA values LESS THAN (TO_DATE('2022-01-01','YYYY-MM-DD'))
);
/
INSERT into t1 (dt)
with dt (dt, interv) as (
select date '2022-01-01', numtodsinterval(1,'DAY') from dual
union all
select dt.dt + interv, interv from dt
where dt.dt + interv < date '2022-02-01')
select dt from dt;
/
I need to split the table into partitions, namely into three partitions according to the EVENT_TIME field, where the first partition is an interval of a week from today, the second last week and the third partition is history, where data that does not pass into the first two partitions are placed.
In addition, I need to add a trigger that will clear the history every two weeks.
CREATE TABLE EVENTS_LOG_TEST_PARTITION
(
ID NUMBER,
METHOD NVARCHAR2(100),
INPUT CLOB,
EVENT_TIME TIMESTAMP(6),
STATUS NVARCHAR2(100),
MESSAGE NVARCHAR2(200)
)
PARTITION BY RANGE (EVENT_TIME)
(
PARTITION CURRENT_WEEK VALUES LESS THAN (TO_DATE(TO_CHAR(CURRENT_TIMESTAMP), 'dd-MM-yyyy HH24:mi:ss'))
)
ENABLE ROW MOVEMENT;
I know that this is not a valid request, so I am writing, please help
It sounds like you want to keep a rolling 2-3 weeks' worth of data. In which case you can use interval partitioning, dropping the oldest partition each week.
Interval partitioning creates a new partition whenever you insert a row with a value greater than the current highest partition boundary.
All you need to define is an initial partition and the time interval. You can choose any value in the past as the boundary for the initial partition.
For example:
create table events_log_test_partition (
id number,
method nvarchar2(100),
input clob,
event_time timestamp(6),
status nvarchar2(100),
message nvarchar2(200)
) partition by range (event_time)
interval ( interval '7' day ) (
partition p_init values less than ( date'2021-01-04' )
);
insert into events_log_test_partition
values ( 1, 'test', 'test', systimestamp - 14, 'test', 'test' );
insert into events_log_test_partition
values ( 2, 'test', 'test', systimestamp, 'test', 'test' );
select partition_name, high_value
from user_tab_partitions
where table_name = 'EVENTS_LOG_TEST_PARTITION';
/*
PARTITION_NAME HIGH_VALUE
P_INIT TIMESTAMP' 2021-01-04 00:00:00'
SYS_P6002 TIMESTAMP' 2021-08-23 00:00:00'
SYS_P6005 TIMESTAMP' 2021-09-06 00:00:00'
*/
select * from events_log_test_partition
partition for ( date'2021-08-18' );
/*
ID METHOD INPUT EVENT_TIME STATUS MESSAGE
1 test test 18-AUG-2021 13.09.17.000000000 test test
*/
select * from events_log_test_partition
partition for ( date'2021-09-01' );
/*
ID METHOD INPUT EVENT_TIME STATUS MESSAGE
2 test test 01-SEP-2021 13.09.17.516073000 test test
*/
alter table events_log_test_partition
drop partition for ( date'2021-08-18' );
select partition_name, high_value
from user_tab_partitions
where table_name = 'EVENTS_LOG_TEST_PARTITION';
/*
PARTITION_NAME HIGH_VALUE
P_INIT TIMESTAMP' 2021-01-04 00:00:00'
SYS_P6005 TIMESTAMP' 2021-09-06 00:00:00'
*/
How can I split maxvalue partition in Oracle with new subpartition template.
Or
How can I split maxvalue partition in Oracle and add also add new subpartitions parallely
You can use SPLIT PARTITION as following:
Oracle setup:
SQL> CREATE TABLE PART_EXAMPLE (
2 ID NUMBER,
3 CREATED_DATE DATE
4 )
5 PARTITION BY RANGE (
6 CREATED_DATE
7 )
8 ( PARTITION T1_2019
9 VALUES LESS THAN ( MAXVALUE )
10 );
Table created.
Checking the partitions:
SQL> SELECT
2 TABLE_NAME,
3 PARTITION_NAME
4 FROM
5 USER_TAB_PARTITIONS
6 WHERE TABLE_NAME = 'PART_EXAMPLE';
TABLE_NAME PARTITION_
--------------- ----------
PART_EXAMPLE T1_2019
Splitting the partition into two partitions:
SQL> ALTER TABLE PART_EXAMPLE
2 SPLIT PARTITION T1_2019 AT (TO_DATE('31-DEC-2017 23:59:59', 'DD-MON-YYYY HH24:MI:SS'))
3 INTO (PARTITION T1_2017, PARTITION T1_2019)
4 ONLINE;
Table altered.
Now, Checking the partitions:
SQL> SELECT
2 TABLE_NAME,
3 PARTITION_NAME
4 FROM
5 USER_TAB_PARTITIONS
6 WHERE TABLE_NAME = 'PART_EXAMPLE';
TABLE_NAME PARTITION_
--------------- ----------
PART_EXAMPLE T1_2017
PART_EXAMPLE T1_2019
SQL>
I hope it is clear.
Cheers!!
You can set the subpartitions template for a table. But this only affects new partitions. It has no impact on existing partitions:
create table t (
c1 int, c2 int
) partition by range ( c1 )
subpartition by hash ( c2 )
subpartition template 2
(
partition p0 values less than ( 1 ),
partition pmax values less than ( maxvalue )
);
select partition_name, subpartition_name
from user_tab_subpartitions
where table_name = 'T';
PARTITION_NAME SUBPARTITION_NAME
P0 SYS_SUBP2922
P0 SYS_SUBP2923
PMAX SYS_SUBP2924
PMAX SYS_SUBP2925
alter table t
set subpartition template 1;
select partition_name, subpartition_name
from user_tab_subpartitions
where table_name = 'T';
PARTITION_NAME SUBPARTITION_NAME
P0 SYS_SUBP2922
P0 SYS_SUBP2923
PMAX SYS_SUBP2924
PMAX SYS_SUBP2925
You can also set the template while splitting. But again, this doesn't affect the existing partitions:
alter table t
split partition pmax at ( 2 )
into (
partition p1 set subpartition template 1,
partition pmax set subpartition template 1
);
select partition_name, subpartition_name
from user_tab_subpartitions
where table_name = 'T';
PARTITION_NAME SUBPARTITION_NAME
P0 SYS_SUBP2922
P0 SYS_SUBP2923
P1 SYS_SUBP2926
P1 SYS_SUBP2927
PMAX SYS_SUBP2924
PMAX SYS_SUBP2925
If you want to change the subpartitions while splitting a partition, define them in the subpartitions clause:
alter table t
split partition pmax at ( 3 )
into (
partition p2 subpartitions 1,
partition pmax subpartitions 4
);
select partition_name, subpartition_name
from user_tab_subpartitions
where table_name = 'T';
PARTITION_NAME SUBPARTITION_NAME
P0 SYS_SUBP2936
P0 SYS_SUBP2937
P1 SYS_SUBP2940
P1 SYS_SUBP2941
P2 SYS_SUBP2942
PMAX SYS_SUBP2943
PMAX SYS_SUBP2944
PMAX SYS_SUBP2945
PMAX SYS_SUBP2946
I have a VARRAYS TYPE wanted to "flatten" the structure with the TABLE expression.
The example data
CREATE OR REPLACE TYPE ARIS.NUMBER_VARRAY_5 AS VARRAY (5) OF NUMBER NOT NULL;
CREATE TABLE ARIS.TEST_2
(
DATE_START DATE,
DATE_END DATE,
O3 ARIS.NUMBER_VARRAY_5,
CATEGORY NUMBER
)
SET DEFINE OFF;
Insert into TEST_2
(DATE_START, DATE_END, O3, CATEGORY)
Values
(TO_DATE('01/01/2005 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('01/05/2005 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), NUMBER_VARRAY_5(281.25,-9999,291.5,310.5,298.75), NULL);
Insert into TEST_2
(DATE_START, DATE_END, O3, CATEGORY)
Values
(TO_DATE('01/02/2005 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('01/06/2005 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), NUMBER_VARRAY_5(-9999,291.5,310.5,298.75,300.75), NULL);
COMMIT;
using the SQL statement
select O3.* from test_2 t, table(t.o3) O3
I can get the result
COLUMN_VALUE
281.25
-9999
291.5
310.5
298.75
-9999
291.5
310.5
298.75
300.75
The question is how I get the results like
DATE_START DATE_END 03.VALUE1 03.VALUE2 03.VALUE3 03.VALUE4 03.VALUE5
01/01/2005 01/05/2005 281.25 -9999 291.5 310.5 298.75
01/02/2005 01/06/2005 -9999 291.5 310.5 298.75 300.75
Try This,
SELECT
*
FROM
(
select
t.Date_start,
t.Date_end,
row_number() OVER ( PARTITION BY DATE_START, DATE_END
ORDER BY
ROWNUM) rn,
O3.*
from
test_2 t,
table(t.o3) O3
)
PIVOT ( MAX(column_value) FOR rn in
(
1 as "03.VALUE1",
2 as "03.VALUE2",
3 as "03.VALUE3",
4 as "03.VALUE4",
5 as "03.VALUE5"
)
) ;