Reputation: 45
I'm struggling with one report contain a varchar2 column as a date in MON-YY format
what I wanna do is convert the value of that column into date so I can do some process on it such as filtering with > or < or even between and set two dates
My column name: BAL.PERIOD_NAME below is the condition cussing error ORA-01843: not a valid month
AND TO_DATE(BAL.PERIOD_NAME,'MON-YY') > TO_DATE('FEB-18','MON-YY')
thanks in advance
Upvotes: 0
Views: 688
Reputation: 59456
Storing date values as strings like 'FEB-18'
is really a design flaw. You should consider a migration to DATE
(or TIMESTAMP
) data type.
Anyway, perhaps it is only a language issue. Try this one
WHERE TO_DATE(BAL.PERIOD_NAME,'MON-RR', 'NLS_DATE_LANGUAGE = American') > DATE '2018-02-01'
In case you are running Oracle 12.2 or later you can use function VALIDATE_CONVERSION:
WHERE VALIDATE_CONVERSION(BAL.PERIOD_NAME, 'MON-RR', 'NLS_DATE_LANGUAGE = American') = 1
If you don't have Oracle 12.2 yet then write your own function, for example like this:
CREATE OR REPLACE FUNCTION CONVERT_TO_DATE(str in VARCAHR2) RETURN DATE IS
BEGIN
RETURN TO_DATE(str, 'MON-RR', 'NLS_DATE_LANGUAGE = American');
EXCEPTION
WHEN OTHERS THEN
RETURN NULL;
END CONVERT_TO_DATE;
Upvotes: 1
Reputation: 1954
Make sure you are using the correct format mask for the date you are converting.
Works:
select TO_DATE('feb-18','MON-YY') from dual
Throws "not a valid month" error:
select TO_DATE('02-18','MON-YY') from dual
Upvotes: 4
Reputation: 37472
You can use a recursive CTE to check you table for invalif month names.
WITH cte(month)
AS
(
SELECT 1 month
FROM dual
UNION ALL
SELECT month + 1 month
FROM cte
WHERE month + 1 <= 12
)
SELECT *
FROM bal
WHERE substr(period_name, 1, 3) NOT IN (SELECT to_char(to_date(month, 'MM'), 'MON')
FROM cte);
Upvotes: 1