In Oracle, a DATE
is a binary data type that consists of 7 bytes representing century, year-of-century, month, day, hours, minutes and seconds. It ALWAYS has those 7 components and it is NEVER stored in any particular human-readable format.
The NLS_DATE_FORMAT
session parameter is the format model Oracle uses for IMPLICIT string-to-date and date-to-string conversions.
If you are performing an string-to-date or date-to-string conversion and are EXPLICIT and specify the format model then your format model will be used in preference to the NLS_DATE_FORMAT
session parameter.
Implicit Date Conversions
If you do:
CREATE TABLE table_name (dt DATE);
Then:
ALTER SESSION SET NLS_DATE_FORMAT='DD-MON-YYYY';
INSERT INTO table_name (dt) VALUES ('27-MAR-2023'); -- A string
INSERT INTO table_name (dt) VALUES (TO_DATE('27-MAR-2023')); -- No format model
Then:
- In the first insert, Oracle will convert the string to a date and implicitly calls
TO_DATE
and will implicitly use the NLS_DATE_FORMAT
session parameter as the format model.
- In the second insert,
TO_DATE
is explicitly called but no format model is specified so Oracle will implicitly use the NLS_DATE_FORMAT
as the format model.
Both of these INSERT
s are effectively the same as:
INSERT INTO table_name (dt) VALUES (
TO_DATE(
'27-MAR-2023',
(SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_DATE_FORMAT')
)
);
Explicit Date Conversions
When you are explicit about the format model:
INSERT INTO table_name (dt) VALUES (TO_DATE('27-MAR-2023', 'DD-MON-YYYY'));
Then Oracle does not need to use the NLS_DATE_FORMAT
.
Handling different date formats
I'm wondering how can I handle different time formats, I've come across several different time formats in others code
Using implicit conversions is considered bad practice. Always explicitly specify the format model and, if you are using language-specific formats then specify the language in the query:
INSERT INTO table_name (dt)
VALUES (TO_DATE('27-MAR-2023', 'DD-MON-YYYY', 'NLS_DATE_LANGUAGE=English'));
or, better, use a DATE
literal:
INSERT INTO table_name (dt) VALUES (DATE '2023-03-27');
Which does not need to be converted from a string to a date and requires no language-specific conversions.
Displaying data
No matter how I set ALTER SESSION SET NLS_DATE_FORMAT='mon-dd-YYYY';
or ALTER SESSION SET NLS_DATE_FORMAT='yyyy.dd.mon';
Nothing changes for my inserted data.
A DATE
is a binary data type and is NEVER stored in any particular human-readable format.
The NLS_DATE_FORMAT
is only used for implicit string-to-date and date-to-string conversions.
If you are displaying dates then the database will provide the client application with the binary value of the date and it is then up to the client application to display that binary value in a meaningful way to the user.
If you are using SQL*Plus or SQL Developer (both Oracle products) then they will both use the NLS_DATE_FORMAT
as the default format for displaying dates. If you are using a different client application (which, for your image, it looks like you are, maybe TOAD or PL/SQL Developer) then how it displays dates is something that that client application controls (and not the database) and if you want to change how it formats dates to display them then you will need to change the settings/preferences in that client application.
If you want to use a specific format and be independent of the client application then you can use TO_CHAR
in a SELECT
statement to convert the binary DATE
to a formatted string:
SELECT dt, -- Formatted by the client application
TO_CHAR(dt), -- Converted to a string by the database
-- Implicitly uses NLS_DATE_FORMAT as the format
-- model.
TO_CHAR(dt, 'DD-MON-YYYY') -- Converted to a string by the database
-- Uses the explicitly provided format model.
FROM table_name;