How to normalize DATE using BEFORE INSERT Trigger / PLSQL Procedure [duplicate] - oracle

ACTUAL
expected
SEP-10-2017
10-SEP-2017
SEP 30 2018
30-SEP-2018
OFFICE OF SMALL
OCT-11-2018
11-OCT-2018
O9-SEP-2009
O9-SEP-2009
Not Applicable
NOV-20-2001
20-NOV-2001
BANIJYA BHIBAG
AUGUST 03 2017
03-AUG-2017
AUG-04-1991
04-AUG-1991
97/2015
09/09/2018
09-SEP-2018
how can we get the result as above and discard the date that cannot be converted?

From Oracle 12, you do not need PL/SQL and can use:
SELECT actual,
COALESCE(
TO_DATE(
actual DEFAULT NULL ON CONVERSION ERROR,
'MM-DD-YYYY',
'NLS_DATE_LANGUAGE=ENGLISH'
),
TO_DATE(
actual DEFAULT NULL ON CONVERSION ERROR,
'DD-MON-YYYY',
'NLS_DATE_LANGUAGE=ENGLISH'
)
) AS parsed
FROM table_name;
Which, for the sample data:
CREATE TABLE table_name (ACTUAL) AS
SELECT 'SEP-10-2017' FROM DUAL UNION ALL
SELECT 'SEP 30 2018' FROM DUAL UNION ALL
SELECT 'OFFICE OF SMALL' FROM DUAL UNION ALL
SELECT 'OCT-11-2018' FROM DUAL UNION ALL
SELECT 'O9-SEP-2009' FROM DUAL UNION ALL
SELECT 'Not Applicable' FROM DUAL UNION ALL
SELECT 'NOV-20-2001' FROM DUAL UNION ALL
SELECT 'BANIJYA BHIBAG' FROM DUAL UNION ALL
SELECT 'AUGUST 03 2017' FROM DUAL UNION ALL
SELECT 'AUG-04-1991' FROM DUAL UNION ALL
SELECT '97/2015' FROM DUAL UNION ALL
SELECT '09/09/2018' FROM DUAL;
Outputs:
ACTUAL
PARSED
SEP-10-2017
10-SEP-2017
SEP 30 2018
30-SEP-2018
OFFICE OF SMALL
OCT-11-2018
11-OCT-2018
O9-SEP-2009
Not Applicable
NOV-20-2001
20-NOV-2001
BANIJYA BHIBAG
AUGUST 03 2017
03-AUG-2017
AUG-04-1991
04-AUG-1991
97/2015
09/09/2018
09-SEP-2018
Note: O9-SEP-2009 has not parsed because you have the letter O rather than the digit 0 as the first character.
db<>fiddle here

One option is to create a function which will cover all possible combinations. The following example has some of them - you'd have to add new when you find them.
SQL> create or replace function f_date (par_str in varchar2)
2 return date
3 is
4 l_date date;
5 begin
6 begin
7 l_date := to_date(par_str, 'mon-dd-yyyy');
8 return l_date;
9 exception
10 when others then null;
11 end;
12
13 --
14
15 begin
16 l_date := to_date(par_str, 'mon dd yyyy');
17 return l_date;
18 exception
19 when others then null;
20 end;
21
22 --
23
24 begin
25 l_date := to_date(par_str, 'dd-mon-yyyy');
26 return l_date;
27 exception
28 when others then null;
29 end;
30
31 --
32
33 begin
34 l_date := to_date(par_str, 'month dd yyyy');
35 return l_date;
36 exception
37 when others then null;
38 end;
39
40 --
41
42 begin
43 l_date := to_date(par_str, 'dd/mm/yyyy');
44 return l_date;
45 exception
46 when others then null;
47 end;
48
49 return null;
50
51 exception
52 when others then
53 return null;
54 end f_date;
55 /
Function created.
Testing:
SQL> select actual, f_date(actual) as expected
2 from test;
ACTUAL EXPECTED
--------------- -----------
SEP-10-2017 10-SEP-2017
SEP 30 2018 30-SEP-2018
OFFICE OF SMALL
09-SEP-2009 09-SEP-2009
Not applicable
AUGUST 03 2017 03-AUG-2017
97/2015
09/09/2018 09-SEP-2018
8 rows selected.
SQL>
Possible problems: if actual = 09/10/12, what is what?
09 can be day, month or year
10 can also be day, month or year
12 can also be day, month or year
So, what is it?
09-OCT-2012
10-SEP-2012
12-OCT-2009
...

If you're sure about that you don't have any other type of the format for those values which can be convertible to a date value(eg.all of the data conform with this sample data set), then use the following code block in order to populate another table(t2) with the decent date values while displaying the rotten values such as
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
dt DATE;
BEGIN
FOR c IN (SELECT * FROM t) LOOP
BEGIN
dt := TO_DATE(c.col, 'MON-DD-YYYY', 'NLS_DATE_LANGUAGE=ENGLISH');
INSERT INTO t2 VALUES(c.id,c.col);
EXCEPTION
WHEN OTHERS THEN
BEGIN
dt := TO_DATE(c.col, 'DD/MM/YYYY', 'NLS_DATE_LANGUAGE=ENGLISH');
INSERT INTO t2 VALUES(c.id,c.col);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(c.col || ' is not a valid date value');
END;
END;
END LOOP;
COMMIT;
END;
/
Demo

Related

How to get the months differences between two dates in oracle sql

Hi team i need to get the exact month differences between two dates i am using oracle sql for my project .here i am trying get the month differences between two dates sat date1 31 AUG 2020 and date_to 01 AUG 2020.i am expecting result 0 month differences but its showing one month
here is my piece of code which i am trying to get
DECLARE
I_DATE DATE;
I_DATE_TO DATE;
I_COUNT_1 NUMBER(10);
BEGIN
I_DATE := TO_DATE ('30/08/2020','dd/mm/yyyy');
I_DATE_TO := TO_DATE ('01/08/2020','dd/mm/yyyy');
SELECT MONTHS_BETWEEN
(TO_DATE(I_DATE,'dd/mm/yyyy'),
TO_DATE(I_DATE_TO,'dd/mm/yyyy') )
into I_COUNT_1
FROM DUAL;
dbms_output.put_line ('I_COUNT_1 = ' || I_COUNT_1);
END;
i am getiing o/p as 1
is there any anothere way to get exact months differences
In your case, it is about resulting variable's datatype.
True result is a decimal number (0.935...):
SQL> DECLARE
2 i_date DATE;
3 i_date_to DATE;
4 i_count_1 DECIMAL;
5 i_count_2 NUMBER;
6 BEGIN
7 i_date := TO_DATE ('30/08/2020', 'dd/mm/yyyy');
8 i_date_to := TO_DATE ('01/08/2020', 'dd/mm/yyyy');
9
10 i_count_1 := MONTHS_BETWEEN (i_date, i_date_to);
11 i_count_2 := MONTHS_BETWEEN (i_date, i_date_to);
12
13 DBMS_OUTPUT.put_line ('I_COUNT_1 = ' || i_count_1);
14 DBMS_OUTPUT.put_line ('I_COUNT_2 = ' || i_count_2);
15 END;
16 /
I_COUNT_1 = 1
I_COUNT_2 = ,935483870967741935483870967741935483871
PL/SQL procedure successfully completed.
SQL>
Now, depending on what you really want (looks like you'd want to get 0), you can truncate the value:
<snip>
15
16 DBMS_OUTPUT.put_line ('truncated i_count_2 = ' || TRUNC (i_count_2));
17 END;
18 /
I_COUNT_1 = 1
I_COUNT_2 = ,935483870967741935483870967741935483871
truncated i_count_2 = 0
PL/SQL procedure successfully completed.
SQL>

How can we extract date only from a column with various date and string formats in Oracle?

ACTUAL
expected
SEP-10-2017
10-SEP-2017
SEP 30 2018
30-SEP-2018
OFFICE OF SMALL
OCT-11-2018
11-OCT-2018
O9-SEP-2009
O9-SEP-2009
Not Applicable
NOV-20-2001
20-NOV-2001
BANIJYA BHIBAG
AUGUST 03 2017
03-AUG-2017
AUG-04-1991
04-AUG-1991
97/2015
09/09/2018
09-SEP-2018
how can we get the result as above and discard the date that cannot be converted?
From Oracle 12, you do not need PL/SQL and can use:
SELECT actual,
COALESCE(
TO_DATE(
actual DEFAULT NULL ON CONVERSION ERROR,
'MM-DD-YYYY',
'NLS_DATE_LANGUAGE=ENGLISH'
),
TO_DATE(
actual DEFAULT NULL ON CONVERSION ERROR,
'DD-MON-YYYY',
'NLS_DATE_LANGUAGE=ENGLISH'
)
) AS parsed
FROM table_name;
Which, for the sample data:
CREATE TABLE table_name (ACTUAL) AS
SELECT 'SEP-10-2017' FROM DUAL UNION ALL
SELECT 'SEP 30 2018' FROM DUAL UNION ALL
SELECT 'OFFICE OF SMALL' FROM DUAL UNION ALL
SELECT 'OCT-11-2018' FROM DUAL UNION ALL
SELECT 'O9-SEP-2009' FROM DUAL UNION ALL
SELECT 'Not Applicable' FROM DUAL UNION ALL
SELECT 'NOV-20-2001' FROM DUAL UNION ALL
SELECT 'BANIJYA BHIBAG' FROM DUAL UNION ALL
SELECT 'AUGUST 03 2017' FROM DUAL UNION ALL
SELECT 'AUG-04-1991' FROM DUAL UNION ALL
SELECT '97/2015' FROM DUAL UNION ALL
SELECT '09/09/2018' FROM DUAL;
Outputs:
ACTUAL
PARSED
SEP-10-2017
10-SEP-2017
SEP 30 2018
30-SEP-2018
OFFICE OF SMALL
OCT-11-2018
11-OCT-2018
O9-SEP-2009
Not Applicable
NOV-20-2001
20-NOV-2001
BANIJYA BHIBAG
AUGUST 03 2017
03-AUG-2017
AUG-04-1991
04-AUG-1991
97/2015
09/09/2018
09-SEP-2018
Note: O9-SEP-2009 has not parsed because you have the letter O rather than the digit 0 as the first character.
db<>fiddle here
One option is to create a function which will cover all possible combinations. The following example has some of them - you'd have to add new when you find them.
SQL> create or replace function f_date (par_str in varchar2)
2 return date
3 is
4 l_date date;
5 begin
6 begin
7 l_date := to_date(par_str, 'mon-dd-yyyy');
8 return l_date;
9 exception
10 when others then null;
11 end;
12
13 --
14
15 begin
16 l_date := to_date(par_str, 'mon dd yyyy');
17 return l_date;
18 exception
19 when others then null;
20 end;
21
22 --
23
24 begin
25 l_date := to_date(par_str, 'dd-mon-yyyy');
26 return l_date;
27 exception
28 when others then null;
29 end;
30
31 --
32
33 begin
34 l_date := to_date(par_str, 'month dd yyyy');
35 return l_date;
36 exception
37 when others then null;
38 end;
39
40 --
41
42 begin
43 l_date := to_date(par_str, 'dd/mm/yyyy');
44 return l_date;
45 exception
46 when others then null;
47 end;
48
49 return null;
50
51 exception
52 when others then
53 return null;
54 end f_date;
55 /
Function created.
Testing:
SQL> select actual, f_date(actual) as expected
2 from test;
ACTUAL EXPECTED
--------------- -----------
SEP-10-2017 10-SEP-2017
SEP 30 2018 30-SEP-2018
OFFICE OF SMALL
09-SEP-2009 09-SEP-2009
Not applicable
AUGUST 03 2017 03-AUG-2017
97/2015
09/09/2018 09-SEP-2018
8 rows selected.
SQL>
Possible problems: if actual = 09/10/12, what is what?
09 can be day, month or year
10 can also be day, month or year
12 can also be day, month or year
So, what is it?
09-OCT-2012
10-SEP-2012
12-OCT-2009
...
If you're sure about that you don't have any other type of the format for those values which can be convertible to a date value(eg.all of the data conform with this sample data set), then use the following code block in order to populate another table(t2) with the decent date values while displaying the rotten values such as
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
dt DATE;
BEGIN
FOR c IN (SELECT * FROM t) LOOP
BEGIN
dt := TO_DATE(c.col, 'MON-DD-YYYY', 'NLS_DATE_LANGUAGE=ENGLISH');
INSERT INTO t2 VALUES(c.id,c.col);
EXCEPTION
WHEN OTHERS THEN
BEGIN
dt := TO_DATE(c.col, 'DD/MM/YYYY', 'NLS_DATE_LANGUAGE=ENGLISH');
INSERT INTO t2 VALUES(c.id,c.col);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(c.col || ' is not a valid date value');
END;
END;
END LOOP;
COMMIT;
END;
/
Demo

ORA-06530: "Reference to uninitialized composite" even if initialized

I have read solutions for solving the error but I don't know why still I get error,
CREATE OR REPLACE TYPE tmp_object IS OBJECT (
id NUMBER,
code NUMBER
);
CREATE OR REPLACE TYPE tmp_table IS TABLE OF tmp_object;
and the anonymous block to use them:
DECLARE
cnt PLS_INTEGER;
tmp_tbl tmp_table := tmp_table();
BEGIN
SELECT regexp_count('34, 87, 908, 123, 645', '[^,]+', 1) str
INTO cnt
FROM dual;
DBMS_OUTPUT.PUT_LINE('Counter is: ' || cnt);
FOR i IN 1..cnt
LOOP
tmp_tbl.EXTEND;
SELECT TRIM(REGEXP_SUBSTR('34, 87, 908, 123, 645', '[^,]+', 1,i)) str
INTO tmp_tbl(tmp_tbl.LAST).code
FROM dual;
DBMS_OUTPUT.PUT_LINE(tmp_tbl(i).code);
END LOOP;
END;
I use Oracle Database 12c and below is the error in SQL Developer 4.2:
Error report -
ORA-06530: Reference to uninitialized composite
ORA-06512: at line 14
00000 - "Reference to uninitialized composite"
*Cause: An object, LOB, or other composite was referenced as a
left hand side without having been initialized.
*Action: Initialize the composite with an appropriate constructor
or whole-object assignment.
The syntax that you are using works for RECORDs
SQL> set serverout on;
SQL>
SQL> DECLARE
2 cnt PLS_INTEGER;
3 l_code NUMBER;
4 TYPE tmp_object IS RECORD (
5 id NUMBER,
6 code NUMBER
7 );
8 TYPE tmp_table IS TABLE OF tmp_object;
9 tmp_tbl tmp_table := tmp_table();
10 BEGIN
11 SELECT regexp_count('34, 87, 908, 123, 645', '[^,]+', 1) str
12 INTO cnt
13 FROM dual;
14
15 DBMS_OUTPUT.PUT_LINE('Counter is: ' || cnt);
16
17 FOR i IN 1..cnt
18 LOOP
19 tmp_tbl.EXTEND;
20
21 SELECT TRIM(REGEXP_SUBSTR('34, 87, 908, 123, 645', '[^,]+', 1,i)) str
22 INTO tmp_tbl(tmp_tbl.LAST).code
23 FROM dual;
24 DBMS_OUTPUT.PUT_LINE(tmp_tbl(i).code);
25
26 END LOOP;
27 END;
28 /
Counter is: 5
34
87
908
123
645
PL/SQL procedure successfully completed
To use OBJECT, you have to use object constructor to insert into the table of that object
SQL>
SQL> CREATE OR REPLACE TYPE tmp_object IS OBJECT (
2 id NUMBER,
3 code NUMBER
4 );
5
6 /
Type created
SQL> CREATE OR REPLACE TYPE tmp_table IS TABLE OF tmp_object;
2 /
Type created
SQL>
SQL> DECLARE
2 cnt PLS_INTEGER;
3 tmp_tbl tmp_table := tmp_table();
4 BEGIN
5 SELECT regexp_count('34, 87, 908, 123, 645', '[^,]+', 1) str
6 INTO cnt
7 FROM dual;
8
9 DBMS_OUTPUT.PUT_LINE('Counter is: ' || cnt);
10
11 FOR i IN 1..cnt
12 LOOP
13 tmp_tbl.EXTEND;
14
15 SELECT tmp_object(i, TRIM(REGEXP_SUBSTR('34, 87, 908, 123, 645', '[^,]+', 1,i)))
16 INTO tmp_tbl(tmp_tbl.last)
17 FROM dual;
18
19 DBMS_OUTPUT.PUT_LINE(tmp_tbl(i).code);
20 END LOOP;
21 END;
22 /
Counter is: 5
34
87
908
123
645
PL/SQL procedure successfully completed
UPDATE: To open a cursor on the collection
You have to use a ref cursor to collect the value from the collection
using TABLE function and CAST function to help oracle identify the
datatype of the collection.
SQL> DECLARE
2 cnt PLS_INTEGER;
3 tmp_tbl tmp_table := tmp_table();
4 c_cursor SYS_REFCURSOR;
5 l_id NUMBER;
6 l_code NUMBER;
7 BEGIN
8 SELECT regexp_count('34, 87, 908, 123, 645', '[^,]+', 1) str INTO cnt FROM dual;
9
10 dbms_output.put_line('Counter is: ' || cnt);
11
12 FOR i IN 1 .. cnt LOOP
13 tmp_tbl.extend;
14
15 SELECT tmp_object(i, TRIM(regexp_substr('34, 87, 908, 123, 645', '[^,]+', 1, i)))
16 INTO tmp_tbl(tmp_tbl.last)
17 FROM dual;
18
19 END LOOP;
20
21 OPEN c_cursor FOR
22 SELECT * FROM TABLE(CAST(tmp_tbl AS tmp_table));
23 LOOP
24 FETCH c_cursor
25 INTO l_id,
26 l_code;
27 EXIT WHEN c_cursor%NOTFOUND;
28 dbms_output.put_line(l_id || ',' || l_code);
29 END LOOP;
30 CLOSE c_cursor;
31
32 END;
33 /
Counter is: 5
1,34
2,87
3,908
4,123
5,645
PL/SQL procedure successfully completed

Getting Ranges from a series of numbers from a table and storing all ranges in a string variable in PLSQL/Oracle Forms

I have a table containing a series of numbers 1,2,3,4,5,11,12,13,14,15,101,102,103,104,105,510,511,512,513,515,516,517.
I want an PL/SQL Function so that I can get the ranges and then store all all the ranges in a single string variable in the following format.
"1-5, 11-15, 101-105, 510-517".
I have get a code to generate the rages in SQL*Plus, but it did not work in PL/SQL and forms. The procedure is given below:
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
2 v_list VARCHAR2(100);
3 BEGIN
4 SELECT listagg(RANGE, ',') WITHIN GROUP(
5 ORDER BY min_num)
6 INTO v_list
7 FROM
8 (SELECT MIN(num) min_num,
9 MIN(num)
10 ||'-'
11 || MAX(num) range
12 FROM
13 (SELECT num, num-Row_Number() over(order by num) AS rn FROM t
14 )
15 GROUP BY rn
16 );
17 dbms_output.put_line(v_list);
18 END;
19 /
1-3,5-7,10-12,20-20
As mentioned here, since the output is a list of strings, you could declare and store the output in a varchar2 variable.
You could create a procedure and put the entire logic in it.
For example,
Setup
SQL> CREATE TABLE t AS
2 SELECT *
3 FROM
4 ( WITH data(num) AS
5 ( SELECT 1 FROM dual
6 UNION
7 SELECT 2 FROM dual
8 UNION
9 SELECT 3 FROM dual
10 UNION
11 SELECT 5 FROM dual
12 UNION
13 SELECT 6 FROM dual
14 UNION
15 SELECT 7 FROM dual
16 UNION
17 SELECT 10 FROM dual
18 UNION
19 SELECT 11 FROM dual
20 UNION
21 SELECT 12 FROM dual
22 UNION
23 SELECT 20 FROM dual
24 )
25 SELECT * FROM DATA);
Table created.
Procedure
SQL> CREATE OR REPLACE
2 PROCEDURE p_get_list
3 AS
4 v_list VARCHAR2(100);
5 BEGIN
6 SELECT listagg(RANGE, ',') WITHIN GROUP(
7 ORDER BY min_num)
8 INTO v_list
9 FROM
10 (SELECT MIN(num) min_num,
11 MIN(num)
12 ||'-'
13 || MAX(num) range
14 FROM
15 (SELECT num, num-Row_Number() over(order by num) AS rn FROM t
16 )
17 GROUP BY rn
18 );
19 dbms_output.put_line(v_list);
20 END;
21 /
Procedure created.
Test case
SQL> SET SERVEROUTPUT ON
SQL> BEGIN
2 p_get_list;
3 END;
4 /
1-3,5-7,10-12,20-20
PL/SQL procedure successfully completed.
You could simply call the procedure in your Oracle Forms.

Wrong calculation for daily partitions

Oracle : 11.2.0.2
I'm trying to drop monthy and daily partitions using a script. This works fine for monthly partitions but not for daily partitions. Below is the error I see in the log. Day of the month is becoming zero when calculating.
2013-08-0|SYS_P328538|2|YES
DECLARE
*
ERROR at line 1:
ORA-01847: day of month must be between 1 and last day of month
ORA-06512: at line 43
Here below is the script. I think highvalue date is miscalculated.
SQL> DECLARE
2 CURSOR tab_part_cur IS
3 select PARTITION_POSITION, PARTITION_NAME,HIGH_VALUE,INTERVAL from dba_tab_partitions where table_name = 'MO_USAGEDATA'
and table_owner = 'WSMUSER17'
order by PARTITION_POSITION;
4 tab_part_rec tab_part_cur%ROWTYPE;
5 lHighValue LONG;
6 strPartitionLessThanDate VARCHAR2(100);
7 dtTestDate DATE;
8 DaysInPast NUMBER;
9 SQLstr varchar2(100);
10 strIntervalType varchar2(1000);
11 strRunType varchar2(20);
12 BEGIN
13 strRunType := 'DRY_RUN';
14 select INTERVAL into strIntervalType from dba_part_tables where table_name ='MO_USAGEDATA' and owner = 'WSMUSER17';
15 strIntervalType := REGEXP_SUBSTR(strIntervalType, '''[^'']+''');
16 DBMS_OUTPUT.PUT_LINE(strIntervalType);
17 CASE
18 WHEN strIntervalType = '''DAY''' THEN
19 DBMS_OUTPUT.PUT_LINE('Interval type = '||strIntervalType);
20 -- dtTestDate := CURRENT_DATE - 7 - 1; Offset adjustment if necessary
21 dtTestDate := CURRENT_DATE - 7;
22 DBMS_OUTPUT.PUT_LINE('Test Date = '||dtTestDate);
23 WHEN strIntervalType = '''MONTH''' THEN
24 DBMS_OUTPUT.PUT_LINE('Interval type = '||strIntervalType);
25 -- dtTestDate := CURRENT_DATE - 90;
26 dtTestDate := ADD_MONTHS(current_date,- 7);
27 DBMS_OUTPUT.PUT_LINE('TestDate = '||dtTestDate);
28 ELSE
29 DBMS_OUTPUT.PUT_LINE('Unexpected interval, exiting.');
30 GOTO EXIT;
31 END CASE;
32 OPEN tab_part_cur;
33 LOOP
34 FETCH tab_part_cur INTO tab_part_rec;
35 EXIT WHEN tab_part_cur%NOTFOUND;
36 DBMS_OUTPUT.PUT_LINE(tab_part_cur%ROWCOUNT);
37 lHighValue := tab_part_rec.high_value;
38 /* This next line seems redundant but is needed for conversion quirk from LONG to VARCHAR2
39 */
40 strPartitionLessThanDate := lHighValue;
41 strPartitionLessThanDate := substr(strPartitionLessThanDate, 11, 10);
42 DBMS_OUTPUT.PUT_LINE(strPartitionLessThanDate ||'|'|| tab_part_rec.partition_name ||'|'|| tab_part_rec.partition_position ||'|'|| tab_part_rec.interval);
43 DBMS_OUTPUT.PUT_LINE(TO_DATE(strPartitionLessThanDate, 'YYYY-MM-DD') ||'******'||dtTestDate);
44 IF TO_DATE(strPartitionLessThanDate, 'YYYY-MM-DD') < dtTestDate AND tab_part_rec.partition_name <> 'PART_MINVALUE
' THEN
45 SQLstr := 'ALTER TABLE WSMUSER17.MO_USAGEDATA DROP PARTITION '||tab_part_rec.partition_name ||' update Global indexes';
46 DBMS_OUTPUT.PUT_LINE('Targeted Partition !!!!!!!!');
47 IF strRunType = 'LIVE_RUN' THEN
48 DBMS_OUTPUT.PUT_LINE('Dropping Partition !!!!!!!!');
49 execute immediate SQLstr;
50 END IF;
51 END IF;
52 END LOOP;
53 CLOSE tab_part_cur;
54 << EXIT >>
55 DBMS_OUTPUT.PUT_LINE('Partition purge complete');
56 END;
57 /
'DAY'
Interval type = 'DAY'
Test Date = 03-SEP-13
1
2012-06-1|PART_MINVALUE|1|NO
01-JUN-12******03-SEP-13
2
2013-08-0|SYS_P328538|2|YES
DECLARE
*
ERROR at line 1:
ORA-01847: day of month must be between 1 and last day of month
ORA-06512: at line 43
I'm trying to keep lat 7 partitions in the daily partitioned table and drop the rest of the partitions. But its not dropping them.
Ok, I created the table, inserted some data and ran some of your queries and you've got something wrong with your substring:
SQL> CREATE TABLE "MO_USAGEDATA" (
2 "REQUESTDTS" TIMESTAMP (9) NOT NULL ENABLE
3 )
4 partition by range ("REQUESTDTS") INTERVAL(NUMTODSINTERVAL(1,'DAY'))
5 (partition PART_MINVALUE values less than(TIMESTAMP '2012-06-18 00:00:00'));
Table created
SQL> INSERT INTO MO_USAGEDATA
2 (SELECT SYSDATE + ROWNUM FROM dual CONNECT BY LEVEL <= 30);
30 rows inserted
SQL> SELECT high_value, INTERVAL
2 FROM all_tab_partitions
3 WHERE table_name = 'MO_USAGEDATA'
4 AND table_owner = USER
5 ORDER BY PARTITION_POSITION;
HIGH_VALUE INTERVAL
------------------------------------ ---------
[...]
TIMESTAMP' 2013-09-30 00:00:00' YES
TIMESTAMP' 2013-10-01 00:00:00' YES
TIMESTAMP' 2013-10-02 00:00:00' YES
[...]
SQL> SELECT substr('TIMESTAMP'' 2013-10-02 00:00:00''', 11, 10) FROM dual;
SUBSTR('TIMESTAMP''2013-10-020
------------------------------
2013-10-0
As you can see you're off by one character. It works with DATE columns, but for TIMESTAMP partitionning, you'll need to adjust the offset.

Resources