5

I have an Oracle DB, and I don't control the date format. I want to know what the date format is to ensure that searches like

select * from search where search_date>='03/16/2016 00:00:00'

work as expected.

entpnerd
  • 10,049
  • 8
  • 47
  • 68

3 Answers3

15

Don't do that - you are relying on implicit data type conversion which is going to fail at some point.

You have two options:

1) Use a proper ANSI SQL date literal:

select * 
from search 
where search_date >= timestamp '2016-03-16 00:00:00';

2) use to_date() (or to_timestamp()) and use a custom format.

select * 
from search 
where search_date >= to_date('03/16/2016 00:00:00', 'mm/dd/yyyy hh24:mi:ss');

With to_date() you should avoid any format that is language dependent. Use numbers for the month, not abbreviations (e.g. 'Mar' or 'Apr') because they again rely on the client language.

More details can be found in the manual:
https://docs.oracle.com/cd/E11882_01/server.112/e41084/sql_elements003.htm#SQLRF51062


Never rely on implicit data type conversion.

Lalit Kumar B
  • 47,486
  • 13
  • 97
  • 124
  • Nice answer but a question. For something like monolithic data warehouses where the date formats won't change, do you really think that it's that bad? For my purposes, I'm just doing one-off queries but I typically forget what the format is when querying data. Of course, a perfectly valid counterargument for what I'm saying is that it's just as easy to use the `to_date` function as it is to do a query first for `NLS_DATE_FORMAT` and then run the lazy query. – entpnerd Mar 16 '16 at 23:05
  • 4
    @entpnerd The date format _can_ change, even in a "monolithic data warehouse" because it is defined by the _client_, not the server (a client with an english operating system will have a different date format then one with e.g. a german operating system). If you typically forget the date format, then stick to the ANSI format - it's the shortest form and will always work regardless of any (explicit or implicit) NLS settings. –  Mar 16 '16 at 23:06
  • 1
    You need to understand that a DATE or TIMESTAMP column is stored in an internal, binary format. What you see are the displayed, character representation. And that is controlled by the setting of NLS_DATE_FORMAT, which can be set at various levels, most of which you will have no control over. I have an article detailing this at http://edstevensdba.com/oracle-data-types/understanding-oracle-date-formats/ – EdStevens Mar 17 '16 at 00:40
  • Just a note, when data type of `SEARCH_DATE` is `DATE` then you **do** an implicit data conversion if you compare with `TIMESTAMP` value - which should be avoided by your own words. – Wernfried Domscheit Mar 17 '16 at 07:55
7

You can get all the NLS session parameters with the query:

SELECT * FROM NLS_SESSION_PARAMETERS;

or, if you have the permissions GRANT SELECT ON V_$PARAMETER TO YOUR_USERNAME;, you can use the command:

SHOW PARAMETER NLS;

If you just want the date format then you can do either:

SELECT * FROM NLS_SESSION_PARAMETERS WHERE PARAMETER = 'NLS_DATE_FORMAT';

or

SHOW PARAMETER NLS_DATE_FORMAT;

However, you could also use ANSI date (or timestamp) literals which are format agnostic. An ANSI date literal has the format DATE 'YYYY-MM-DD' and a timestamp literal has the format TIMESTAMP 'YYYY-MM-DD HH24:MI:SS.FF9'. So your query would be:

select * from search where search_date>= DATE '2016-03-16'

or

select * from search where search_date>= TIMESTAMP '2016-03-16 00:00:00'
MT0
  • 143,790
  • 11
  • 59
  • 117
  • 1
    @DS. Do not rely on the default date format being consistent as it is a session parameter set by the user's client (not the server) - meaning that each user can set the value in their own session so two users can have different values or, even that, one user can have different values in different sessions - this is especially true in international organisations where the client default will depend on the territory/language defaults of the client. Either use a date/timestamp literal or use `TO_DATE` with an explicit format model. – MT0 Mar 29 '18 at 10:02
0

What is Oracle's Default Date Format?

A DATE doesn't have any format. Oracle does not store dates in the format you see. It stores it internally in 7 bytes with each byte storing different components of the datetime value.

Byte    Description
----    -------------------------------------------------
1       Century value but before storing it add 100 to it
2       Year and 100 is added to it before storing
3       Month
4       Day of the month
5       Hours but add 1 before storing it
6       Minutes but add 1 before storing it
7       Seconds but add 1 before storing it

To display, use TO_CHAR with proper FORMAT MODEL.

For comparing, use TO_DATE with proper FORMAT MODEL.

What you see as a format by default, is your locale specific NLS settings.

SQL> select parameter, value from v$nls_parameters where parameter='NLS_DATE_FORMAT';

PARAMETER       VALUE
--------------- ----------------------------------------------------------------
NLS_DATE_FORMAT DD-MON-RR

SQL> select sysdate from dual;

SYSDATE
---------
17-MAR-16

SQL> select to_char(sysdate, 'mm/dd/yyyy hh24:mi:ss') from dual;

TO_CHAR(SYSDATE,'MM
-------------------
03/17/2016 12:48:41

SQL>

search_date>='03/16/2016 00:00:00'

You are comparing a DATE with a string literal. Always, explicitly convert the string into date using TO_DATE and proper format mask.

TO_DATE('03/16/2016', 'MM/DD/YYYY')

Or, if you dealing only with the date part and not concerned with the time portion, then use the ANSI date literal which uses a fixed format DATE 'YYYY-MM-DD'

DATE '2016-03-16'

You might just be lucky to get an output due to an implicit datatype conversion based on your locale specific NLS settings. Never ever rely on implicit datatype conversion, it might work for you, might fail for others where the nls settings are different.

Lalit Kumar B
  • 47,486
  • 13
  • 97
  • 124
  • There are [two date formats](http://stackoverflow.com/a/13568348/1509264): Type 12 has 7 bytes (`SELECT DUMP(date_column) FROM table_name`) and Type 13 has 8 bytes (`SELECT DUMP(SYSDATE) FROM DUAL`). – MT0 Mar 17 '16 at 09:27
  • Those are two types not formats. Format doesn't mean the internal byte representation. Especially, for OP who assumes the display to be the date format. – Lalit Kumar B Mar 17 '16 at 11:12
  • Ok, replace "formats" with "data structures" in my previous comment. However, the point still stands that your first section on the byte structure of dates is only half the story as there is an 8-byte structure that is also used for dates. – MT0 Mar 17 '16 at 11:15
  • @MT0 For storing dates in table, the 7 bytes are enough. The 8th byte is for internal DATE functions like SYSDATE or externally where you need to use TO_DATE to convert it. This topic is about storing dates, so **when you store a date in the table, take the dump and see it will be Len=7 even if you use SYSDATE or TO_DATE while inserting**. – Lalit Kumar B Mar 17 '16 at 11:25