SELECT MONTHS_BETWEEN(LAST_DAY('15-JAN-12') + 1, '01-APR-12')
FROM DUAL;
ERROR : not a valid month
SELECT MONTHS_BETWEEN(LAST_DAY('15-JAN-12') + 1, '01-APR-12')
FROM DUAL;
ERROR : not a valid month
'15-JAN-12'
is not a date; it is a string literal that happens to look like a date. Oracle will try to be helpful and will try to convert the string to a date and will implicitly convert your query to the equivalent of:
SELECT MONTHS_BETWEEN(
LAST_DAY(
TO_DATE(
'15-JAN-12',
(SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_DATE_FORMAT')
)
) + 1,
TO_DATE(
'01-APR-12',
(SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_DATE_FORMAT')
)
)
FROM DUAL;
Which may give you the correct answer if the NLS_DATE_FORMAT
is DD-MON-RR
.
However, if you use:
ALTER SESSION SET NLS_DATE_FORMAT = 'fxDD-MM-YYYY';
Then the same query outputs:
ORA-01858: a non-numeric character was found where a numeric was expected
and if you use:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
then it is even worse, the query doesn't fail it outputs the unexpected value 165.6451612903226
.
What you should do is not rely on implicit conversions and always use explicit conversion (and, if you are using a specific language then specify the language as well):
SELECT MONTHS_BETWEEN(
LAST_DAY(
TO_DATE('15-JAN-12', 'DD-MON-RR', 'NLS_DATE_LANGUAGE=English')
) + 1,
TO_DATE('01-APR-12', 'DD-MON-RR', 'NLS_DATE_LANGUAGE=English')
)
FROM DUAL;
Or, you can use a date literal:
SELECT MONTHS_BETWEEN(
LAST_DAY(
DATE '2012-01-15'
) + 1,
DATE '2012-04-01'
)
FROM DUAL;
You need to use the TO_DATE()
function to convert a string to a date literal.
SELECT MONTHS_BETWEEN(LAST_DAY(TO_DATE('15-JAN-12', 'dd-mmm-yyy')) + 1, TO_DATE('01-APR-12', 'dd-mmm-yyy'))
FROM DUAL;
You can also use date literals, which are written as DATE 'YYYY-MM-DD'
SELECT MONTHS_BETWEEN(LAST_DAY(DATE '2012-01-15') + 1, DATE '2012-04-01')
FROM DUAL;
Usually Oracle expects the month part to be written in full form (e.g. JANUARY, APRIL). Try this: SELECT MONTHS_BETWEEN(LAST_DAY('15-JANUARY-12') + 1, '01-APRIL-12') FROM DUAL;