If you try to perform an explicit cast using CAST(value AS TIMESTAMP), or an equivalent implicit cast such as in your query, from the string values to a timestamp then Oracle will implicitly convert the cast to the equivalent of:
TO_TIMESTAMP(
value,
(SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_TIMESTAMP_FORMAT')
)
If you have the sample data:
CREATE TABLE table_name (value) AS
SELECT '2022-01-21 2:49:38.251' FROM DUAL UNION ALL
SELECT '22-01-21 2:49:38.251000' FROM DUAL;
You can see it in action using:
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'DD-MON-RR HH24.MI.SSXFF';
SELECT value,
TO_CHAR(
CAST(value AS TIMESTAMP),
'YYYY-MM-DD HH24:MI:SS.FF'
) AS converted_value
FROM table_name;
Outputs the error:
ORA-01843: not a valid month
As, given the string-to-date conversion rules the MON format model will also match MONTH but it will not match the numeric MM format so the 01 month generates the error.
However:
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'RR-MM-DD HH24:MI:SSXFF'
SELECT value,
TO_CHAR(
CAST(value AS TIMESTAMP),
'YYYY-MM-DD HH24:MI:SS.FF'
) AS converted_value
FROM table_name;
Outputs:
| VALUE |
CONVERTED_VALUE |
| 2022-01-21 2:49:38.251 |
2022-01-21 02:49:38.251000 |
| 22-01-21 2:49:38.251000 |
2022-01-21 02:49:38.251000 |
Both the rows are converted as expected.
If, instead, you use:
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SSXFF'
SELECT value,
TO_CHAR(
CAST(value AS TIMESTAMP),
'YYYY-MM-DD HH24:MI:SS.FF'
) AS converted_value
FROM table_name;
Then the output is:
| VALUE |
CONVERTED_VALUE |
| 2022-01-21 2:49:38.251 |
2022-01-21 02:49:38.251000 |
| 22-01-21 2:49:38.251000 |
0022-01-21 02:49:38.251000 |
And the first row converts as expected but the second row the YYYY format model matches 22 and gives 22 AD rather than 2022 AD (as was probably expected).
If you want to compare to a timestamp then either use an explicit conversion:
SELECT *
FROM EMPLOYEE
WHERE CREATE_TIME = TO_TIMESTAMP(
'2022-01-21 2:49:38.251',
'YYYY-MM-DD HH24:MI:SSXFF'
)
Or a timestamp literal:
SELECT *
FROM EMPLOYEE
WHERE CREATE_TIME = TIMESTAMP '2022-01-21 02:49:38.251'
If you rely on the NLS parameters then your query may have different (and unexpected) behaviours for different sessions (sometimes even for different sessions of the same user).
db<>fiddle here