Skip to Main Content

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Bill.

Asked: June 25, 2000 - 6:00 pm UTC

Last updated: May 29, 2019 - 6:21 am UTC

Version: 8.1.0

Viewed 100K+ times! This question is

You Asked

hi Tom,

i saw your FAQ regarding this but couldn't find the answer.

my initORCL.ora's nls_date_format is being ignored!

is there a way to adjust sqlplus so it uses a certain date format always - other than by using a sql statement or a trigger to set it automatically on login? i want to use ANSI "YYYY-MM-DD"

my nls_lang is set to american - not sure if that's relevant. you mentioned on windows this could be achieved by editing the client's registry entries - is there somthing similar for linux? i didn't see any config settings for sqlplus.

i was able to use the alter session statement. how would i implement the trigger solution if editing the registry isn't an option?

thanks!
Bill

and Tom said...

The faq reference is </code> http://asktom.oracle.com/Misc/NLSDateFormat.html <code>

Its not being ignored, its being overridden. If you set *any* NLS parameter -- they all default.

On 8.1, using an ON-LOGON trigger would be my preferred method if you want this to take effect for absolutely every client that connects. In this fashion, regardless of the client environemnt, you are assured the date format will be what you want it to be until the client application itself changes it.

short of that, you can set an environment variable as you did for NLS_LANG above. The environment in unix is in place of the registry in NT. Here is an example. I started with an 8i instance with the nls_date_format set to dd-mon-rrrr in the init.ora. My environment has NO nls_* parameters to start:

$ sqlplus scott/tiger

SQL*Plus: Release 8.1.5.0.0 - Production on Mon Jun 26 06:55:19 2000
(c) Copyright 1999 Oracle Corporation. All rights reserved.
Connected to:
Oracle8i Enterprise Edition Release 8.1.5.1.0 - Production
With the Partitioning and Java options
PL/SQL Release 8.1.5.1.0 - Production


scott@ORACLE8I> select sysdate from dual;

SYSDATE
-----------
26-jun-2000

So, here the nls_date_format from the init.ora is being used. Lets add NLS_LANG to the environment:

scott@ORACLE8I> Disconnected from Oracle8i Enterprise Edition Release 8.1.5.1.0 - Production
With the Partitioning and Java options
PL/SQL Release 8.1.5.1.0 - Production

$ setenv NLS_LANG american

$ sqlplus scott/tiger

SQL*Plus: Release 8.1.5.0.0 - Production on Mon Jun 26 06:55:48 2000

(c) Copyright 1999 Oracle Corporation. All rights reserved.


Connected to:
Oracle8i Enterprise Edition Release 8.1.5.1.0 - Production
With the Partitioning and Java options
PL/SQL Release 8.1.5.1.0 - Production

scott@ORACLE8I> select sysdate from dual;

SYSDATE
---------
26-JUN-00

That shows we are back to the default DD-MON-YY format. Lets fix it:

scott@ORACLE8I> exit
Disconnected from Oracle8i Enterprise Edition Release 8.1.5.1.0 - Production
With the Partitioning and Java options
PL/SQL Release 8.1.5.1.0 - Production


$ setenv NLS_DATE_FORMAT "dd-mon-yyyy hh24:mi:ss"


$ sqlplus scott/tiger

SQL*Plus: Release 8.1.5.0.0 - Production on Mon Jun 26 06:56:33 2000

(c) Copyright 1999 Oracle Corporation. All rights reserved.


Connected to:
Oracle8i Enterprise Edition Release 8.1.5.1.0 - Production
With the Partitioning and Java options
PL/SQL Release 8.1.5.1.0 - Production

scott@ORACLE8I> select sysdate from dual;

SYSDATE
--------------------
26-jun-2000 06:56:37

scott@ORACLE8I>

And thats it - the environment variable fixes the default date format.

Again -- i'm partial to the on-logon trigger myself.

Rating

  (73 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

default nls_date_format

A reader, June 04, 2002 - 7:40 pm UTC

Hi Tom,
Referring to the comment:
"That shows we are back to the default DD-MON-YY format"
Should it not be DD-MON-RR? If not, how did you know that it is DD-MON-YY?
Thanks


Tom Kyte
June 05, 2002 - 6:30 am UTC

yes, it is rr in 8i and up, yy in 8.0 and before

Reader

A reader, June 06, 2002 - 11:47 am UTC

Tom,

The default format for Oracle is DD-MON-RR for Oracle 8i
SQL>select sysdate from x$dual;
06-JUN-02
SQL>set time on
11:39:30 SQL>

When I try to do
SQL>recover database until time '30-MAY-02 11:00:00' ;
I ger ORA-00351

However when I subsequently do

SQL>alter session set nls_date_format = 'yyyy-mm-dd hh24:mi:ss';
SQL>recover database until time '2002-05-30 11:00:00';
It is successful

How to find what does Oracle use for nls_format when doing recovery

Thanks 

Tom Kyte
June 06, 2002 - 4:30 pm UTC

The sqlplus guide documents the format used for the recover command:

UNTIL TIME date

Specifies an incomplete, time-based recovery. Use single quotes, and the
following format:
’YYYY-MM-DD:HH24:MI:SS’




Reader

A reader, June 06, 2002 - 4:45 pm UTC

SQL> alter session set nls_date_format = 'mm/dd/yyyy hh24:mi:ss';

SQL> recover database until time '05/24/2002 10:49:30' using 
     backup controlfile;
ORA-01843: not a valid month

The following format works although not the documented format:
--------------------------------------------------------------
SQL> alter session set nls_date_format = 'mon/dd/yyyy hh24:mi:ss';

Session altered.

SQL> recover database until time 'may/29/2002 17:04:23' 
     using backup controlfile;

recovery complete
 

Tom Kyte
June 06, 2002 - 6:12 pm UTC

and did you try just

recover database until time ’YYYY-MM-DD:HH24:MI:SS’ ....

as documented?

Reader

A reader, June 07, 2002 - 7:16 am UTC

I tried first

recover database until time ’YYYY-MM-DD:HH24:MI:SS’ ....
It works as well

Thanks

Tom Kyte
June 07, 2002 - 8:16 am UTC

Yes, we are happy with a : or a space in there when the date format is set to:

ops$tkyte@ORA817DEV.US.ORACLE.COM> alter session set nls_date_format = 'yyyy-mm-dd hh24:mi:ss';

Session altered.

ops$tkyte@ORA817DEV.US.ORACLE.COM> select to_date( '2001-01-01 00:00:00' ) from dual;


TO_DATE('2001-01-01
-------------------
2001-01-01 00:00:00

ops$tkyte@ORA817DEV.US.ORACLE.COM> c/1 0/1:0
  1* select to_date( '2001-01-01:00:00:00' ) from dual
ops$tkyte@ORA817DEV.US.ORACLE.COM> /

TO_DATE('2001-01-01
-------------------
2001-01-01 00:00:00

ops$tkyte@ORA817DEV.US.ORACLE.COM>


See -- it can (or cannot) have a : in there when the format is set to that.  Your setting of the nls_date_format has nothing to do with the recover command - there is but one format (the one documented) -- it just happens both strings work with it. 

Reader

A reader, June 07, 2002 - 12:56 pm UTC

Tom,

Thanks for the clarification

ORA-12801: error signaled in parallel query server P002

Sikandar Hayat Awan, July 25, 2002 - 11:39 pm UTC

I am getting the following error on one table in the same session of sql/plus .

ERROR:
ORA-12801: error signaled in parallel query server P002
ORA-01843: not a valid month

My test is as below,

Oracle 8.1.7 on WIN-NT4 SP5

scott > select sysdate from dual;

SYSDATE
----------
26/07/2002

scott > select * from emp_barcode where prod_date = '15/07/2002';
ERROR:
ORA-12801: error signaled in parallel query server P000
ORA-01843: not a valid month



no rows selected

scott > select * from emp_barcode where scan_date = '15/07/2002'
scott > /
ERROR:
ORA-12801: error signaled in parallel query server P001
ORA-01843: not a valid month



no rows selected

scott > select * from emp_incentives where prod_date = '15/07/2002'
<<<<<<<<<<< displays records>>>>>>>>>>>>>>>>>>

scott > select * from emp_barcode where prod_date = to_date('15/07/2002','dd/mm/yyyy');
<<<<<<<<<<< displays records>>>>>>>>>>>>>>>>>>

scott > alter session set nls_date_format = 'DD/MM/YYYY';

Session altered.

scott > select * from emp_barcode where prod_date = '15/07/2002';
<<<<<<<<<<< displays records>>>>>>>>>>>>>>>>>>

I have checked Oracle DOCS and while searching here I found this thread so posting here.

My questions are,
In the same session nls_date settings should be same?
Is there any problem with this table?
I was not getting this error earlier and I have not changed anything on the server or client?

Tom Kyte
July 26, 2002 - 6:44 am UTC

Word of advice.

compare strings to strings.

dates to dates

numbers to numbers

Always -- forever and always. Never compare a date to a string, a number to a string, and so on. Implicit conversions will *kill you* as they are here.


You know what to do here, use to_date and never compare a date to a string again.



My problem is different

Sikandar Hayat Awan, July 26, 2002 - 10:27 pm UTC

Before posting I was thinking that what will be your answer and today found the same answer. I know that I should use date = date and I am using it. Here my question is this whats wrong that in one query it is giving me results while in other an error. I am not using date = string in my applications but some time we have to check the tables data from sql/plus so it is time consuming to write to_date(...) while oracle will take no time to convert as it is one time query.

Here my question is that is there any problem with the table or it is an abnormal situation as this is first time I am getting this error.

You are talking about performance but I am worried about the DB configuration or any side effects.

Why oracle is unable to convert string to date on this table while doing on others?

>> I know it will work date=date.

Tom Kyte
July 28, 2002 - 3:26 pm UTC

sorry, time consuming or not -- your problem *is no different* (other then you are willing to say "its my fault, it is too much work to type in the correct query"

type in the correct and proper query. period.

I don't know how many times in this lifetime I will type in:

compare

dates to dates
strings to strings
numbers to numbers


But it's in the thousands already (from way BEFORE doing SQL actually -- back in my PL/I mainframe programming days!)

I'm not talking about performance -- I'm talking *ALWAYS* about getting the right answer.

NLS_DATE_FORMAT ANSWER?

Nigel Evenden, April 20, 2003 - 2:32 pm UTC

I followed the suggested answer to the letter, but was still unsuccessful, having changed the Registry and changed my init.ora file. The only thing that seems to work is the ALTER SESSION method - not good enough!

Any more thoughts?

Thanks

Nigel

Tom Kyte
April 20, 2003 - 2:59 pm UTC

you did something wrong -- you fixed the "wrong" NLS_DATE format. you might find you have many of them -- or you might find whatever tool you are using issues an ALTER SESSION itself.


the alter session should not only be good enough -- it is far superior then relying on a registry setting that could change on you. If your application needs a date format -- it should set it. thats the only way to be sure of anything.

Set NLS_DATE_FORMAT env. variable in your Windows environment...

Kamal Kishore, April 20, 2003 - 10:13 pm UTC

No need to edit the registry. All you need is to create a System variable NLS_DATE_FORMAT in your Windows environment.

For Windows2000, Right click on "My Computer" icon and click on properties. Then click on Advanced tab and then click "Environment Variables" to create NLS_DATE_FORMAT env. variable.

See the following example to see the effect of changing the environment variable inside the MS-DOS session:

=========================================================
C:\>echo %NLS_DATE_FORMAT%
DD-MON-YYYY

C:\>sqlplus scott/tiger

SQL*Plus: Release 9.2.0.1.0 - Production on Sun Apr 20 22:05:05 2003

Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.


Connected to:
Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.1.0 - Production

SQL> select sysdate from dual ;

SYSDATE
-----------
20-APR-2003

SQL> exit
Disconnected from Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.1.0 - Production

C:\>set NLS_DATE_FORMAT=YYYY-MM-DD

C:\>sqlplus scott/tiger

SQL*Plus: Release 9.2.0.1.0 - Production on Sun Apr 20 22:05:27 2003

Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.


Connected to:
Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.1.0 - Production

SQL> select sysdate from dual ;

SYSDATE
----------
2003-04-20

SQL> exit
Disconnected from Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.1.0 - Production

C:\>
=========================================================
 

mubeen, July 06, 2003 - 5:15 am UTC

you said,
"On 8.1, using an ON-LOGON trigger would be my preferred method if you want this to take effect for absolutely every client that connects. In this fashion, regardless of the client environemnt, you are assured the date format will be what you want it to be until the client application itself changes it."

Can you please give an example of ON-LOGON trigger for that pupose. And is there any other environment variables can be set using ON-LOGON trigger?

Thanks


Tom Kyte
July 06, 2003 - 10:01 am UTC

just click on the link I provided in the answer above.

what about webserver

Susan, September 10, 2003 - 6:07 pm UTC

Default PC installation sets NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1 which defaults to a DD-MON-YY date format. If I change the registry setting on the Webserver will that overide the date format being set b/c of client NLS_LANG setting? Thanks.

Tom Kyte
September 10, 2003 - 8:24 pm UTC



if you are using a webserver to access the database, the client settings are "meaningless", the client IS the webserver -- the client is NOT the pc.

ORA - 01843, ORA - 01839

Abdul, September 24, 2003 - 6:34 am UTC

hai,
I have a table

pisterm
-------
milit_no number(38)
term_date number(28)
......

sample data
miltno term_date
-------------------
1000714 80449198
1000822 80109698
1000992 80138998

I need to insert/ update term_date into some other table.
I used
TO_DATE(TO_NUMBER(99999999-TERM_DATE),'YYYYMMDD') to convert. It updated some records and then it is giving ORA-01843,ORA-01839 errors. I can display records using query...

SELECT TO_DATE(TO_NUMBER(99999999-TERM_DATE),'YYYYMMDD')
FROM aisha.PISTERM_COUNT WHERE MILITARY_NO > 1012800

output
---------
14-SEP-87
25-JUN-94
10-JUN-90
01-SEP-94
05-DEC-95
01-AUG-92
30-JUL-86
30-AUG-97
08-MAY-76
18-NOV-97..
.........

but I cannot update using

update pisterm
set date_type_col = TO_DATE(TO_NUMBER(99999999-TERM_DATE),'YYYYMMDD')
where MILITARY_NO > 1012800;

ORA - 01843 NOT A VALID MONTH


PLEASE HELP ME

Tom Kyte
September 24, 2003 - 9:46 am UTC

seems pretty clear to me:

[tkyte@localhost tkyte]$ oerr ora 1843
01843, 00000, "not a valid month"
// *Cause:
// *Action:
[tkyte@localhost tkyte]$ oerr ora 1839
01839, 00000, "date not valid for month specified"
// *Cause:
// *Action:


you have some values of term_date in there such that when you do your math -- you are getting months that are not between 1..12 and days that are outside the range for the month.

you have "bad data"

Ask Tom "nls_date_format"

curtis keller, October 14, 2003 - 1:14 am UTC

Great information. We often forget other countries have other date formats - and sometimes the user of the SQLPLUS - did not set the defaults.

And we failed to "convert / compare dates to dates"



ORA-01843: not a valid month

manhcuong, March 27, 2004 - 9:18 am UTC


OK

Maria, April 02, 2004 - 8:06 am UTC

Dear Tom,
How to find out the international languages supported by
Oracle?Is there any data dictionary view that can be queried to find out the languages supported by Oracle?
Please do reply.
Bye!


Tom Kyte
April 02, 2004 - 10:20 am UTC

see the globalization guide.

comparing with sysdate not giving proper result...

Kiran Shah, August 13, 2004 - 8:16 am UTC

While we are comparing our entry date field with sysdate for counting no. of records, it is not giving proper results.

Details is given below...
SQL> alter session set nls_date_format='dd/mm/rrrr'
  2  ;

Session altered.

SQL> create table dttest
  2  (empno number(4),
  3  entrydate date);

Table created.

SQL> insert into table(1,sysdate);
insert into table(1,sysdate)
            *
ERROR at line 1:
ORA-00903: invalid table name 


SQL> insert into dttest values(1,sysdate);

1 row created.

SQL> insert into dttest values(2,sysdate);

1 row created.

SQL> insert into dttest values(3,sysdate);

1 row created.

SQL> select count(*) from dttest
  2  where entrydate=sysdate;

 COUNT(*)                                                                                           
---------                                                                                           
        0                                                                                           

SQL> select count(*) from dttest
  2  where to_char(entrydate,'dd/mm/rrrr')='13/08/2004';

 COUNT(*)                                                                                           
---------                                                                                           
        3                                                                                           

SQL> spool off

Does it mean that every time when we need to count, we have to convert into char ?


 

Tom Kyte
August 13, 2004 - 4:36 pm UTC

sysdate has yyyy mm dd hh24 mi ss

entrydate has it too.

a date has a "day" as well as "time"

if you don't want the "time", insert into dttest values ( 1, TRUNC(sysdate) );

and use TRUNC(sysdate) when comparing.


your to_char didn't include the time component is all.

Some additional info...

Kiran Shah, August 13, 2004 - 8:21 am UTC

We are using Oracle 9i database on RedHat server.
And development is done on Windows.

We also tried to set nls_date_format as environment variable in windows.

Thanks,
Kiran Shah

Still one more doubt...

Kiran Shah, August 16, 2004 - 3:18 am UTC

Tom,

Thanks...

I now understood this date things more clearly...But one more doubt...

In our Forms, we are using date fields, which have format property as 'dd/mm/rrrr' and in our queries we are comparing simply as follows :

select * from proceedings
where entrydate = :caseprocc.listingdate;

As I understood, I think that we have to use trunc function whenever we want to compare dates only.

So do we need to change queries as ...

select * from proceedings
where trunc(entrydate) = :caseprocc.listingdate;


(The first query gives us correct result so far...)


Kiran.

Tom Kyte
August 16, 2004 - 8:29 am UTC

you are using the DATE type in forms -- yes or no.

does your entrydate include a time component? if entered from forms, probably not. select count(*) from t where entrydate <> trunc(entrydate) would tell you.

Is this a Bug ?

pasko, January 20, 2005 - 5:40 am UTC

Hi Tom, 

Take a look at the following.

Why is this new Data type behaving strangely ?


My aim is to get the same functionality as that offered by add_months ,but also i want to be able to add specific Seconds/Minutes/Days .


SQL> alter session set nls_date_format = 'DD.MM.YYYY HH24:MI:SS' ;

Session wurde geändert.

SQL> SELECT LAST_DAY(  SYSDATE  ) + INTERVAL  '0000-01'   YEAR (4) TO MONTH    next_mon1 from dual ;

SELECT LAST_DAY(  SYSDATE  ) + INTERVAL  '0000-01'   YEAR (4) TO MONTH    next_mon1 from dual
                             *
FEHLER in Zeile 1:
ORA-01839: date not valid for month specified



SQL> SELECT   ADD_MONTHS(  LAST_DAY(SYSDATE) , 1 )  next_mon2 from dual ;

NEXT_MON2
-------------------
28.02.2005 11:30:23


SQL> SELECT LAST_DAY(  SYSDATE  )      +    to_yminterval('0000-01')     next_mon1 from dual ;
SELECT LAST_DAY(  SYSDATE  )      +    to_yminterval('0000-01')     next_mon1 from dual
                                  *
FEHLER in Zeile 1:
ORA-01839: date not valid for month specified 

Tom Kyte
January 20, 2005 - 10:30 am UTC

that is the defined behavior of the ANSI function -- we have to implement interval math the way the standard dictates and the standard said "that is the way we want this to work"

(so use add_months....)


or last_day the result of adding 1 month to the TRUNC of sysdate to the first day of the month... (reverse the order of your operations)

How ?

pasko, January 20, 2005 - 12:04 pm UTC

Hi Tom,


Thanks for your Response.


i didn't understand the last paragraph though, can you please provide an sql example for :


"
or last_day the result of adding 1 month to the TRUNC of sysdate to the first
day of the month... (reverse the order of your operations)
"

Thanks in advance.




Tom Kyte
January 20, 2005 - 7:14 pm UTC

last_day( trunc(sysdate) + interval_of_one_month )

instead of last_day(sysdate)+interval_of_one_month


but - you know, add_months seems to be the right answer for you.

A reader, February 28, 2005 - 8:40 am UTC


A reader, April 07, 2005 - 1:48 pm UTC


How can Use this function like this...it's not working for me

janet, June 28, 2005 - 9:46 am UTC

str := ''''||swToDelete|| '-' || '0''';-- = '1-0'
deleteDays_1 := TO_YMINTERVAL(str);


Tom Kyte
June 28, 2005 - 10:16 am UTC

i've no idea what you are even trying to do?

Tom

A reader, June 28, 2005 - 10:56 am UTC

swToDelete holds a value equivalent to years
I am trying to call the TO_YMINTERVAL function
to get a specific time interval in terms of years and months
then I take that interval and break it down in to days.
using dynamic sql.

below is the an example of what I am doing.

DECLARE
x TIMESTAMP WITH TIME ZONE;
y INTERVAL YEAR TO MONTH;
BEGIN

x := TIMESTAMP '2002-07-14 21:15:00 -07:00';
y := INTERVAL '0-1' YEAR TO MONTH;
x := x + y;
x := x + INTERVAL '1 00:00:00' DAY TO SECOND;
DBMS_OUTPUT.PUT_LINE(TO_CHAR(
x, 'yyyy-mm-dd hh24:mi:ss tzh:tzm'));
END;
/

2002-08-15 21:15:00 -07:00


Tom Kyte
June 28, 2005 - 11:34 am UTC

use

numtoyminterval( 1, 'year' ) or numtoyminterval(1,'month') or whatever you need.

don't play with strings if you don't have to.

THANKS!!

A reader, June 28, 2005 - 12:02 pm UTC

Do you have any examples here where it's done dynamically?

Thanks again!

Tom Kyte
June 28, 2005 - 12:47 pm UTC

just replace the number one with a variable?

Is it possible to add filler to the format string for date?

Kate Oh, September 29, 2005 - 2:08 pm UTC

We have applications expecting date field value returned in the format "YYYY-MM-DD-HH24.MI.SS.000000". where 000000 are trading fillers. When I excute alter session with the format I get ORA-01821: date format not recognized error. I tried various options but didn't work. We want to have this format database wise so the clients don't have to set each time they logon. What could be the best solution to achieve this?
Thanks a lot.

Tom Kyte
September 30, 2005 - 8:40 am UTC

do you mean this?

ops$tkyte@ORA10G> alter session set nls_date_format = 'YYYY-MM-DD-HH24.MI.SS".000000"';
 
Session altered.
 
ops$tkyte@ORA10G> select sysdate from dual;
 
SYSDATE
--------------------------
2005-09-30-08.33.15.000000
 
ops$tkyte@ORA10G> select to_date( '2005-09-30-08.33.15.000000' ) from dual;
 
TO_DATE('2005-09-30-08.33.
--------------------------
2005-09-30-08.33.15.000000
 

How does one find out "nls_date_format" in effect

VKOUL, October 19, 2005 - 2:10 pm UTC

Hi Tom,

Is it possible for a user in Oracle to find the "nls_date_format" string having only "create session" privileges ?

Thanks


Tom Kyte
October 19, 2005 - 4:27 pm UTC

ops$tkyte@ORA10GR2> drop user a cascade;

User dropped.

ops$tkyte@ORA10GR2> create user a identified by a;

User created.

ops$tkyte@ORA10GR2> grant create session to a;

Grant succeeded.

ops$tkyte@ORA10GR2>
ops$tkyte@ORA10GR2> connect a/a
Connected.
a@ORA10GR2> select * from nls_database_parameters;

PARAMETER                      VALUE
------------------------------ ----------------------------------------
NLS_LANGUAGE                   AMERICAN
NLS_TERRITORY                  AMERICA
NLS_CURRENCY                   $
NLS_ISO_CURRENCY               AMERICA
NLS_NUMERIC_CHARACTERS         .,
NLS_CHARACTERSET               WE8ISO8859P1
NLS_CALENDAR                   GREGORIAN
NLS_DATE_FORMAT                DD-MON-RR
NLS_DATE_LANGUAGE              AMERICAN
NLS_SORT                       BINARY
NLS_TIME_FORMAT                HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT           DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT             HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT        DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY              $
NLS_COMP                       BINARY
NLS_LENGTH_SEMANTICS           BYTE
NLS_NCHAR_CONV_EXCP            FALSE
NLS_NCHAR_CHARACTERSET         AL16UTF16
NLS_RDBMS_VERSION              10.2.0.1.0

20 rows selected.

 

VKOUL, October 19, 2005 - 8:11 pm UTC

Thanks Tom.

How does one find out "nls_date_format" in effect

VKOUL, October 19, 2005 - 8:21 pm UTC

Hi Tom,

Even if I change "nls_date_format" to something else like 'DD-MON-YYYY HH24:MI:SS', the nls_database_parameters still shows me the same old value, how can I see what is in effect at current time.

SQL> select * from nls_database_parameters;

PARAMETER                      VALUE
------------------------------ ----------------------------------------
NLS_LANGUAGE                   AMERICAN
NLS_TERRITORY                  AMERICA
NLS_CURRENCY                   $
NLS_ISO_CURRENCY               AMERICA
NLS_NUMERIC_CHARACTERS         .,
NLS_CHARACTERSET               WE8ISO8859P1
NLS_CALENDAR                   GREGORIAN
NLS_DATE_FORMAT                DD-MON-RR
NLS_DATE_LANGUAGE              AMERICAN
NLS_SORT                       BINARY
NLS_TIME_FORMAT                HH.MI.SSXFF AM

PARAMETER                      VALUE
------------------------------ ----------------------------------------
NLS_TIMESTAMP_FORMAT           DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT             HH.MI.SSXFF AM TZH:TZM
NLS_TIMESTAMP_TZ_FORMAT        DD-MON-RR HH.MI.SSXFF AM TZH:TZM
NLS_DUAL_CURRENCY              $
NLS_COMP                       BINARY
NLS_NCHAR_CHARACTERSET         WE8ISO8859P1
NLS_RDBMS_VERSION              8.1.7.0.0

18 rows selected.

SQL> 
SQL> 
SQL> 
SQL> 
SQL> 
SQL> alter session set nls_date_format='DD-MON-YYYY HH24:MI:SS';

Session altered.

SQL> select * from nls_database_parameters;

PARAMETER                      VALUE
------------------------------ ----------------------------------------
NLS_LANGUAGE                   AMERICAN
NLS_TERRITORY                  AMERICA
NLS_CURRENCY                   $
NLS_ISO_CURRENCY               AMERICA
NLS_NUMERIC_CHARACTERS         .,
NLS_CHARACTERSET               WE8ISO8859P1
NLS_CALENDAR                   GREGORIAN
NLS_DATE_FORMAT                DD-MON-RR
NLS_DATE_LANGUAGE              AMERICAN
NLS_SORT                       BINARY
NLS_TIME_FORMAT                HH.MI.SSXFF AM

PARAMETER                      VALUE
------------------------------ ----------------------------------------
NLS_TIMESTAMP_FORMAT           DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT             HH.MI.SSXFF AM TZH:TZM
NLS_TIMESTAMP_TZ_FORMAT        DD-MON-RR HH.MI.SSXFF AM TZH:TZM
NLS_DUAL_CURRENCY              $
NLS_COMP                       BINARY
NLS_NCHAR_CHARACTERSET         WE8ISO8859P1
NLS_RDBMS_VERSION              8.1.7.0.0

18 rows selected.

SQL> 
SQL> disc
Disconnected from Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production
With the Partitioning option
JServer Release 8.1.7.0.0 - Production
SQL>  

I got it

VKOUL, October 19, 2005 - 11:45 pm UTC

It is "nls_session_parameters"

Thanks Tom

NLS_DATE parameter

A reader, December 06, 2005 - 2:17 am UTC

I was searching internet for nls_date_format I found your Q & A are useful and help for me.
Thanks very much

ORA-01843: not a valid month

Shailesh Saraff, December 15, 2005 - 1:01 pm UTC

Hello Tom,

Last few days we are observing ORA-01843: not a valid month, error continously. On startup our Application always sets date format to dd.mm.yyyy format using ALTER SESSION SET NLS_DATE_FORMAT = 'DD.MM.YYYY';

But error occurs on following statement.
SELECT Type, Module FROM TableTypeModule
WHERE NVL(TRUNC(BeginDate), '01.01.1800') <= TRUNC(SYSDATE)
AND TRUNC(EndDate) >= TRUNC(SYSDATE);

We have also done following to check, what was the date format when this error occurs and to check in case someone else has set other date format, but even following trace/debug trigger shows DD.MM.YYYY format. We can't change all queries in our application to set date format explicitly.

CREATE OR REPLACE TRIGGER TrgDB_003
AFTER SERVERERROR ON DATABASE
DECLARE
sprogram VARCHAR2 (200);
smachine VARCHAR2 (200);
sosuser VARCHAR2 (200);
NLSHost VARCHAR2 (4000);
NLSDate VARCHAR2 (4000);
NLSLang VARCHAR2 (4000);
SPID VARCHAR2 (10);
sid number;
serial number;
BEGIN

IF (is_servererror (1843))
THEN
SELECT NVL (b.Program, b.Module), machine, OSUser, a.SPID,
SYS_CONTEXT ('USERENV', 'HOST'),
SYS_CONTEXT ('USERENV', 'NLS_DATE_FORMAT'),
SYS_CONTEXT ('USERENV', 'NLS_DATE_LANGUAGE'), b.SID, b.Serial#
INTO sProgram, smachine, sosuser, SPID, NLSHost,
NLSDate,
NLSLang, SId, serial
FROM SYS.v_$session b, v$process a
WHERE audsid = USERENV ('SESSIONID') AND A.Addr = B.Paddr;

INSERT INTO TempTraceInformation
(EventTime, Program, machine, osuser,
Information, TraceFileSPID,
NLSHost, NLSDate, NLSLang, sid, serial
)
VALUES (SYSDATE, sprogram, smachine, sosuser,
'Caught ORA-1843 exception with this program', SPID,
NLSHost, NLSDate, NLSLang, sid, serial
);

END IF;
END;
/

We are really in need of help to resolve this issue, please help. How can we track that date format?

Thanks & Regards,

Shailesh



Tom Kyte
December 15, 2005 - 1:15 pm UTC

if you are observing this "continously", then it is reproducible?

what is the output of

select to_char( to_date( '01-02-2005', 'dd-mm-yyyy' ) ) from dual;


?

ORA-01843

Shailesh Saraff, December 16, 2005 - 5:04 am UTC

Hi Tom,

Before setting nls_date_format above query shows 01-FEB-05 and after ALTER SESSION SET NLS_DATE_FORMAT = 'DD.MM.YYYY'; 01.02.2005.

The problem is that error doesn't come continuesly, When everyone starts working after hour or so it starts coming on few sessions not at all sessions.

Is there any other way to track the same. Please let me know.

Thanks & Regards,

Shailesh

Tom Kyte
December 16, 2005 - 8:39 am UTC

sounds like something must be changing the date format somehow?

You may contact support, they can describe how to generate a stack trace with more diagnostic information upon hitting this error that might be useful in tracking this down.

clarification

amit poddar, January 21, 2006 - 1:01 pm UTC

SQL> select to_date(sysdate,'mm/dd/yyyy hh24:mi:ss') from dual;
select to_date(sysdate,'mm/dd/yyyy hh24:mi:ss') from dual
               *
ERROR at line 1:
ORA-01843: not a valid month


SQL> 

why the error above. It should have converted to the right format . Am I missing something here

SQL> show parameters nls_date

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
nls_date_format                      string      DD-MON-RR
nls_date_language                    string

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE    10.2.0.1.0      Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production

 

Tom Kyte
January 21, 2006 - 6:20 pm UTC

that is the same as:

select to_date( TO_CHAR(sysdate), 'mm/dd/yyyy hh24:mi:ss' )


(since to_date expects a char)... Which is in your case the same as:

select to_date( TO_CHAR(sysdate,'DD-MON-RR'), 'mm/dd/yyyy hh24:mi:ss' )


which is sort of like:


select to_date( '01-JAN-06', 'mm/dd/yyyy hh24:mi:ss' )


which obviously would not work.

more clarification

amit poddar, January 21, 2006 - 7:01 pm UTC

  1  select to_date(to_char(sysdate,'mm/dd/yyyy hh24:mi:ss'),
  2*                'mm/dd/yyyy hh24:mi:ss') from dual
SQL> /

TO_DATE(T
---------
21-JAN-06


why does this not give the date in requested format ? 

Tom Kyte
January 22, 2006 - 9:34 am UTC

now you have:


select TO_CHAR( to_date( to_char( sysdate,...),.... ) from dual;
^^^^^^^

there is an implicit TO_CHAR performed on numbers and dates when converted into strings (which is what SQL Plus is doing)

So, since your default date mask is in fact DD-MON-RR, you are getting just what you asked for.


Question for you: what is your goal? To display a date in a particular format? If so, explicitly use TO_CHAR to format the internal 7 byte date format into whatever you would like it to look like. Just one to_char - no to_date of to_char of to_date of to_char'ing - just one function call.

date to string to date to default date string format

jim, January 21, 2006 - 8:48 pm UTC

because you converted a date to a string and then back to a date and then sqlplus used the default date to string format. (you can't see a date unless you display it as converted to a string.)

thanks jim

A reader, January 21, 2006 - 9:51 pm UTC


not quite the answer...

Tyler, January 22, 2006 - 12:09 am UTC

Amit, when you listed your NLS settings you showed the following. 

SQL> show parameters nls_date

NAME                                 TYPE        VALUE
------------------------------------ ----------- ---------
nls_date_format                      string      DD-MON-RR


if you want to see the timestamp information when you're in SQLPLUS you'll have to alter your NLS_DATE_FORMAT

it's simple enough to do on the session level, run the following when you log into a SQLPLUS session:

alter session set NLS_DATE_FORMAT='mm/dd/yyyy hh24:mi:ss'

or set the format to whatever you'd like in order to see your dates in that specific format. 

enjoy.  

understood

amit poddar, January 22, 2006 - 11:11 am UTC

My goal was just to understand all this stuff. I was confused. You clarified my confusion

thanks


Why AFTER LOGON is not working ?

Kiran Shah, February 06, 2006 - 5:11 am UTC

I want date format in 'dd/mm/yyyy' format for all connections.

So I created the trigger as shown in your link..

create or replace trigger data_logon_trigger
after logon
ON DATABASE
begin
execute immediate
'alter session set nls_date_format = ''dd/mm/yyyy'' ';
end;
/

After this, if I re-connect to database, it still shows the date in DD-MON-RR format.

Any idea why it is not working ?

(However, if I run simply these statements,
begin
execute immediate
'alter session set nls_date_format = ''dd/mm/yyyy'' ';
end;
/
then it alter the session as desired.)

We have Oracle 9i (Release 1.0)

Thanks,
Kiran.

Tom Kyte
February 07, 2006 - 12:37 am UTC

ops$tkyte@ORA9IR2> create or replace trigger data_logon_trigger
  2  after logon
  3  ON DATABASE
  4  begin
  5      execute immediate
  6          'alter session set nls_date_format = ''dd/mm/yyyy'' ';
  7  end;
  8  /

Trigger created.

ops$tkyte@ORA9IR2> connect /
Connected.
ops$tkyte@ORA9IR2> select sysdate from dual;

SYSDATE
----------
07/02/2006


working fine for me - you don't have _system_trig_enabled set to false do you? 

Date is not showing properly in SYS user...

Kiran Shah, February 07, 2006 - 2:42 am UTC

Excellent help Sir...

_system_trig_enabled was set to false. I changed it and now it is working.

But in SYS user, date is shown in different format. 

Here is what is happening exactly...

SQL> select sysdate from dual;  (from other user)

SYSDATE
----------
07/02/2006

SQL> connect sys as sysdba
Connected.
SQL> select sysdate from dual;

SYSDATE
---------
07/02/200

SQL> connect ccis/filing
Connected.
SQL> select sysdate from dual;

SYSDATE
----------
07/02/2006

SQL> spool off;

In SYS user the year is shown as 200 only. What could be the possible reason ?

Thanks again for your help...

Kiran 

Tom Kyte
February 07, 2006 - 5:22 am UTC

you should never ever be connecting as sysdba for stuff - beyond say "startup and shutdown". So, I am not entirely too concerned - but sysdba is special, magic, different.

(sqlplus is messing up here -

dd-mon-rr
07/02/200

it is truncating the formated date string)

do not use SYSDBA day to day. It is special, magic, different. It is not to be used for "normal" things.

Ok. Thanks....

Kiran Shah, February 08, 2006 - 1:41 am UTC

Ok. Sir,

Will keep in mind your advise. And also as such we are not using SYS for day to day usage.

This SYS result was found out while checking result of AFTER LOGON trigger for different users.

Thanks,
Kiran.

Query on date comparison

Krishna, February 10, 2006 - 5:50 am UTC

SQL> select * from nls_session_parameters
  2  where parameter = 'NLS_DATE_FORMAT';

PARAMETER                      VALUE
--------------------------------------------------
NLS_DATE_FORMAT                DD-Mon-YYYY HH24:MI

SQL> select fordate, wake_time from sleep_log;

FORDATE           WAKE_TIME
----------------- -----------------
08-Feb-2006 00:00 08-Feb-2006 07:30
09-Feb-2006 00:00 09-Feb-2006 08:00
10-Feb-2006 00:00 10-Feb-2006 07:45
07-Feb-2006 00:00 07-Feb-2006 08:00
01-Feb-2006 00:00 01-Feb-2006 07:45
31-Jan-2006 00:00 31-Jan-2006 08:00
02-Feb-2006 00:00 02-Feb-2006 07:30
03-Feb-2006 00:00 03-Feb-2006 08:30
06-Feb-2006 00:00 06-Feb-2006 07:37

9 rows selected.

SQL> alter session set nls_date_format='yyyy';

Session altered.

SQL> select fordate, wake_time from sleep_log where fordate='31-Jan-2006';
select fordate, wake_time from sleep_log where fordate='31-Jan-2006'
                                                       *
ERROR at line 1:
ORA-01830: date format picture ends before converting entire input string

This has behaved as I had expected - the format is set to YYYY and the conversion doesn't succeed. 

SQL> select fordate, wake_time from sleep_log where fordate='2006';

FORD WAKE
---- ----
2006 2006

Why does this give me only one row when there are 9 rows that should have been fetched? 

Tom Kyte
February 10, 2006 - 12:58 pm UTC

ops$tkyte@ORA10GR2> select to_char( to_date( '2006', 'YYYY' ), 'dd-mon-yyyy hh24:mi:ss' ) from dual;
 
TO_CHAR(TO_DATE('200
--------------------
01-feb-2006 00:00:00



your date after the (bad, horrible, don't do it) implicit conversion of '2006' into the date is in fact 01-feb-2006.

Next month, it'll be 01-mar-2006

Last month it was 01-jan-2006


IMPLICIT CONVERSIONS ARE REALLY BAD.  Stop doing them, period.


And when in doubt, use to_char to see what you actually have there. 

Got it...

Krishna, February 11, 2006 - 12:24 pm UTC

Understand your point and the implications of relying on implicit conversion. Reliance on implicit conversions, a definite no-no.

extra period new in 10 g

A reader, February 24, 2006 - 3:01 pm UTC

Hi

I have compatibility problem from Oracle 10G 
and the NLS_DATE_LANGUAGE parameter.

In 9i and 10g, the result of to_char() gives different 
results when using CANADIAN FRENCH.

Oracle 9i
==========================
Connected to:
Oracle9i Enterprise Edition Release 9.2.0.6.0 - 64bit Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.6.0 - Production

SQL> alter session set nls_date_language='AMERICAN';

Session altered.

SQL> SELECT TO_CHAR(SYSDATE, 'DY MON') from dual;

TO_CHAR
-------
FRI FEB

SQL> alter session set nls_date_language='CANADIAN FRENCH';

Session altered.

SQL> SELECT TO_CHAR(SYSDATE, 'DY MON') from dual;

TO_CHAR
-------
VEN FEV



Oracle 10G
======================
SQL*Plus: Release 9.2.0.1.0 - Production on Fri Feb 24 13:41:59 2006

Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.

Connected to:
Oracle Database 10g Enterprise Edition Release 10.1.0.4.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options

SQL> alter session set nls_date_language='AMERICAN';

Session altered.

SQL> SELECT TO_CHAR(SYSDATE, 'DY MON') from dual;

TO_CHAR
-------
FRI FEB


SQL> alter session set nls_date_language='CANADIAN FRENCH';

Session altered.

SQL> SELECT TO_CHAR(SYSDATE, 'DY MON') from dual;

TO_CHAR(SY
----------
VEN. FEVR.




How can we get the same results we had in Oracle 9i?


Thanks a lot
Oscar 

Tom Kyte
February 24, 2006 - 6:35 pm UTC

please utilize support for something like this - beyond me showing how to use replace to turn the '.' into nothing and or using substr - there won't be much I can do.



A reader, June 13, 2006 - 8:00 am UTC


NLS_DATE_FORMAT

Amol R Tambolkar, June 27, 2006 - 9:53 am UTC

Good One ! ON-LOGON trigger are very much useful as far as our application requires sysdate in a particular format which is diff default.

Thanks !!
- Amol R Tambolkar

Even better idea on NLS_DATE_FORMAT

Mahmood Lebbai, June 27, 2006 - 6:56 pm UTC

I am not sure whether people have explored this option

To have this setting available to everyone who logs on we could have this alter session statement in the glogin.sql statement which is available in the folder

‘ORACLE_HOME \ sqlplus \ admin \‘

Append this statement in there :

‘Alter session set NLS_DATE_FORMAT=’mm/dd/yyyy hh:mi:ss’

This will reflect the date setting globally for all users. I guess this would be even better idea than to write Trigger which Tom accepts partially. No matter which database you are getting connected to, this will get reflected in the SQL client. Since this is more of client side setting.

Tom, you may express your comments on this…Am I right on the money?

Please read this Oracle article on “Oracle Database 10g: The Top 20 Features for DBAs” which supports this idea....

</code> http://www.oracle.com/technology/pub/articles/10gdba/week7_10gdba.html?_template=/ocom/technology/content/print <code>


Tom Kyte
June 28, 2006 - 7:42 am UTC

only for sqlplus would this work. Meaning, it would not work for any other application. Meaning - glogin.sql is not really a good idea in general as it doesn't fix the problem for your applications.

IF you want this to be set for only SQLPLUS,
THEN
login.sql or glogin.sql could be used


Save the day

Mahmood Lebbai, June 28, 2006 - 1:30 pm UTC

Since SQLPlus tool is ubiquitous...this should save the day for many DBAs and Developers... ;-)



Tom Kyte
June 28, 2006 - 4:57 pm UTC

not really - since it is pretty much the APPLICATIONS that need this, not a command line tool...

Can't get it to work from the top of my head..

A reader, June 28, 2006 - 5:18 pm UTC

I know this is very basic stuff, but I have tried in almost all the servers I have access to around here.

I am trying to set nls_date_format environment variable before  login to sqlplus but it is not recognizing it for some reason. Can you point me into what I am doing wrong ? Thanks.

Here's an example:

# su - oracle
Sun Microsystems Inc.   SunOS 5.9       Generic May 2002
$ env | grep NLS
$ NLS_DATE_FORMAT="dd-mm-yyyy";export NLS_DATE_FORMAT
$ env | grep NLS
NLS_DATE_FORMAT=dd-mm-yyyy
$ sqlplus '/ as sysdba'

SQL*Plus: Release 10.1.0.5.0 - Production on Wed Jun 28 05:18:14 2006

Copyright (c) 1982, 2005, Oracle.  All rights reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.1.0.5.0 - 64bit Production
With the Partitioning and Data Mining options

SQL> select sysdate from dual;

SYSDATE
---------
28-JUN-06

SQL> show parameter nls_date_format

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
nls_date_format                      string
SQL>
SQL> !env | grep NLS
NLS_DATE_FORMAT=dd-mm-yyyy

SQL> exit
Disconnected from Oracle Database 10g Enterprise Edition Release 10.1.0.5.0 - 64bit Production
With the Partitioning and Data Mining options

I have tried with other users as well with no avail. Thanks! 

Tom Kyte
June 28, 2006 - 6:33 pm UTC

did you set your NLS_LANG?

That needs to be set.

10g queries having issue with TIMESTAMP WITH LOCAL TZ columns

Suresh, July 20, 2006 - 9:24 am UTC

create table tt (x number, y timestamp with local time zone);

create unique index tt_uk on tt(x, y);

declare
i number;
begin
for i in 1..1000
loop
insert into tt values(i, systimestamp+1);
end loop;
end;
/
commit;

set autotrace on explain statistics;

--Below query will do "unique scan" (of tt_uk) in 9i where as it will do "range scan" in 10g.
select * from tt where x=50 and y=to_timestamp_tz('21-JUL-06','DD-MON-YY');

Due to this change in execution path, queries comparing timestamps, have slowed down considerably in 10g.

Any idea what needs to be tweaked in 10g to fix it?


Tom Kyte
July 22, 2006 - 4:50 pm UTC

well, in 10g, the create index gathered statistics by default, whereas in 9i it will not.  You did not gather stats on the table - and the CBO is the default. so, lets see:


ops$tkyte%ORA10GR2> create table tt (x number, y timestamp with local time zone);

Table created.

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> create unique index tt_uk on tt(x, y);

Index created.

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> declare
  2   i number;
  3  begin
  4   for i in 1..1000
  5   loop
  6   insert into tt values(i, systimestamp+1);
  7   end loop;
  8  end;
  9  /

PL/SQL procedure successfully completed.

ops$tkyte%ORA10GR2> commit;

Commit complete.

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> set autotrace traceonly explain
ops$tkyte%ORA10GR2> select * from tt where x=50 and y=to_timestamp_tz('21-JUL-06','DD-MON-YY');

Execution Plan
----------------------------------------------------------
Plan hash value: 2533825380

--------------------------------------------------------------------------
| Id  | Operation        | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT |       |     1 |    26 |     2   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| TT_UK |     1 |    26 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("X"=50)
       filter(SYS_EXTRACT_UTC(INTERNAL_FUNCTION("Y"))=SYS_EXTRACT_UTC(TO
              _TIMESTAMP_TZ('21-JUL-06',:B1)))

Note
-----
   - dynamic sampling used for this statement

ops$tkyte%ORA10GR2> set autotrace off


Actually, I cannot reproduce - but I can say:

a) either move the create index until AFTER you load the data or gather statistics on it, since you - well, massively changed the data from "zero stuff" to "not zero stuff"

b) gather stats on the table after loading


 

Modified version of above example

Suresh, July 21, 2006 - 1:19 am UTC

OK. I will present problem in a different way. While querying columns of type TIMESTAMP (and which are indexes) we see FULL TABLE SCAN in 10g where as INDEX RANGE SCAN in 9i. Below is the test case:

DROP TABLE TT;

CREATE TABLE TT (X TIMESTAMP WITH LOCAL TIME ZONE);
CREATE INDEX TT_IND ON TT(X);

DECLARE
I NUMBER;
BEGIN
FOR I IN 1..10000
LOOP
INSERT INTO TT VALUES(trunc(SYSTIMESTAMP)+I);
END LOOP;
END;
/

COMMIT;



begin
dbms_stats.gather_table_stats(ownname=>'TCA',
tabname=>'TT',
estimate_percent=> NULL,
GRANULARITY =>'ALL',
CASCADE=>TRUE,
METHOD_OPT =>'FOR ALL COLUMNS SIZE AUTO');
end;
/

SET AUTOTRACE ON EXPLAIN STATISTICS;

SELECT * FROM TT WHERE X=TO_TIMESTAMP_TZ(trunc(SYSTIMESTAMP+10), 'DD-MON-YYYY HH:MI:SS AM');

Above SELECT query performs FULL TABLE scan in 10g where as it uses TT_IND index in 9i?





Tom Kyte
July 22, 2006 - 5:52 pm UTC

see my example above, see the implicit function? That is the reason "why". Looks like a bug fix. It was wrong in 9i.


"local time zone" (database column)

vs

"server time zone" (to_timestamp_tz)


<quote>
TO_TIMESTAMP_TZ converts char of CHAR, VARCHAR2, NCHAR, or NVARCHAR2 datatype to a value of TIMESTAMP WITH TIME ZONE datatype.
</quote>

with time zone datatype - not local time zone.

<quote>
TIMESTAMP WITH LOCAL TIME ZONE is another variant of TIMESTAMP that includes a time zone offset in its value. It differs from TIMESTAMP WITH TIME ZONE in that data stored in the database is normalized to the database time zone, and the time zone offset is not stored as part of the column data. When a user retrieves the data, Oracle returns it in the user's local session time zone. The time zone offset is the difference (in hours and minutes) between local time and UTC (Coordinated Universal Time—formerly Greenwich Mean Time). This datatype is useful for displaying date information in the time zone of the client system in a two-tier application.
</quote>


So, it looks wrong in 9i


Thanks Tom

Suresh, July 24, 2006 - 12:33 am UTC

Yes you are right... 9i bug fixed in 10g. However, we are in trouble while migrating to 10g. So, is below fix appropriate?

CAST(TO_TIMESTAMP_TZ(trunc(SYSTIMESTAMP+10), 'DD-MON-YYYY
HH:MI:SS AM') as TIMESTAMP WITH LOCAL TIME ZONE)

This works with above example but we wanted to confirm it's correct fix
OR
Is there better solution?

THANK YOU VERY MUCH FOR YOUR KIND SUPPORT!!

Tom Kyte
July 24, 2006 - 10:06 am UTC

you have to tell me - are you assured of GETTING THE RIGHT ANSWER??? Look at what it is doing, is it *correct* given your application logic?

Suresh, July 31, 2006 - 1:35 am UTC

Yes it works OK for our application (not sure, if i confused you in above sample code - SORRY).

nls_date_format in windows?

Interested, August 16, 2006 - 3:58 pm UTC

wondering if anybody else has run into this same issue.  with nls_date_format mm/dd/rr i get different behavior inserting dates through sqlplus in windows vs. linux.  In Linux inserting date 25-JUN-2006 fails with error Not a Valid month.  It does not fail and inserts the correct date in Windows.  Would expect this to fail in both.  I do not have any NLS environment variables set on either the Linux or Windows clients.

SQL> show parameter nls_date_format

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
nls_date_format                      string      mm/dd/rr

SQL> create table x (d date);

Table created.

On Linux Client ...
SQL> insert into x values ('25-JUN-2006');
insert into x values ('25-JUN-2006')
                      *
ERROR at line 1:
ORA-01843: not a valid month

On Windows Client ...
SQL> insert into x values ('25-JUN-2006');

1 row created.

SQL> select * from x;

D
---------
25-JUN-06 

Tom Kyte
August 16, 2006 - 5:28 pm UTC

sure you do on windows - absolutely sure of that.

It does it in the install - NLS_LANG is set.


select * from nls_session_parameters;

see what you see.
</code> http://asktom.oracle.com/Misc/NLSDateFormat.html <code>

Strange behaivour of concatenating date with string.

A reader, August 29, 2006 - 7:51 pm UTC

Tom, could you please help me on to how do I avoid the date casting as string, and thus totally changing the meaning on this situation ?

SQL>
SQL> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
PL/SQL Release 9.2.0.1.0 - Production
CORE    9.2.0.1.0       Production
TNS for Compaq Tru64 UNIX: Version 9.2.0.1.0 - Production
NLSRTL Version 9.2.0.1.0 - Production

SQL> select * from nls_session_parameters where parameter = 'NLS_DATE_FORMAT';

PARAMETER                      VALUE
------------------------------ ----------------------------------------
NLS_DATE_FORMAT                DD/MM/YYYY

SQL> select thedate from t;

THEDATE
----------
01/08/0000
01/08/0000
01/08/0000

SQL> select thedate||chr(44) from t;

THEDATE||CH
-----------
00/00/0000,
00/00/0000,
00/00/0000,

SQL>

You see, it totally changes the answer when I concatenate it with a comma (I am seeing this behaivour when using a technique of yours with sqlldr_exp to export the results to flat files).

Thanks! 

Tom Kyte
August 30, 2006 - 8:01 am UTC

It would appear that your "thedate" is already munged - broken, invalid - or are you really storing "year zero" stuff.

RE: Strange behaivour of concatenating date with string

A reader, August 30, 2006 - 8:53 am UTC

Actually, the data is being inserted from one legacy application we have around here. I created a sample data creating this table T. Even when I select it from a different client (say, OEM sql scratchpad) it shows me a different date (in this case, it is 01-aug-0001). It is stopping me from extracting the data with sqlldr_exp and then inserting it again with sqlldr (it complains with day must be between 1 and last day of month). If I could come with a solution (even within the manners of sqlldr) that would be helpfull.

Thanks!

Tom Kyte
August 30, 2006 - 9:02 am UTC

your dates are botched, your legacy application must be using "binary 7 byte dates" and they have put garbage in there.

</code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:21127620973437 <code>



SQL LOADEER

Mohan, September 17, 2006 - 8:16 am UTC

Lang = en_US -- This is already available in my UNIX environment

I have set the environment variable as 
set env NLS_DATE_FORMAT=YYMMDD 
from the $ prompt

Then logged through SQL*PLUS in the same session of my unix environment.

SQL> select sysdate from dual;

SYSDATE
---------
17-SEP-06

I would like to know what I am missing here..
and also would like to know whether NLS_LANG or NLS_DATE_FORMAT will take precedence if we have both.

Environment.

Oracle -- Oracle9i Enterprise Edition Release 9.2.0.4.0 - 64bit Production 
Unix -- AIX 

 

Tom Kyte
September 17, 2006 - 8:25 am UTC

what is "lang=en_US"? 


if you have your NLS_LANG set, and you set the NLS_DATE_FORMAT, all should be "OK"


[tkyte@dellpe ~]$ export NLS_DATE_FORMAT=yyyymmdd
[tkyte@dellpe ~]$ !env
env | grep NLS
NLS_DATE_FORMAT=yyyymmdd


[tkyte@dellpe ~]$ plus

SQL*Plus: Release 10.2.0.2.0 - Production on Sun Sep 17 08:15:51 2006

Copyright (c) 1982, 2005, Oracle.  All Rights Reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.2.0 - Production
With the Partitioning, OLAP and Data Mining options

ops$tkyte%ORA10GR2> select sysdate from dual;

SYSDATE
---------
17-SEP-06

ops$tkyte%ORA10GR2> exit
Disconnected from Oracle Database 10g Enterprise Edition Release 10.2.0.2.0 - Production
With the Partitioning, OLAP and Data Mining options


[tkyte@dellpe ~]$ export NLS_LANG=AMERICAN_AMERICA.US7ASCII
[tkyte@dellpe ~]$ !env
env | grep NLS
NLS_LANG=AMERICAN_AMERICA.US7ASCII
NLS_DATE_FORMAT=yyyymmdd
[tkyte@dellpe ~]$ plus

SQL*Plus: Release 10.2.0.2.0 - Production on Sun Sep 17 08:16:02 2006

Copyright (c) 1982, 2005, Oracle.  All Rights Reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.2.0 - Production
With the Partitioning, OLAP and Data Mining options

ops$tkyte%ORA10GR2> select sysdate from dual;

SYSDATE
--------
20060917

ops$tkyte%ORA10GR2>
 

This forum seems very useful. I have one doubt on nls_date_format

Robin, April 27, 2009 - 3:17 am UTC

nls_date_format is not printing date in correct format.

When i do a select sysdate from dual. its showing correctly.

But when i try to use it inside a procedure to write to a file it displays onlt "dd/mm/yy".

nls_date_format is given correctly in parameter table.

Could you please help
Tom Kyte
April 27, 2009 - 2:20 pm UTC

define what you mean by "correctly"

what have you set it to????!

http://asktom.oracle.com/~tkyte/Misc/NLSDateFormat.html

Bala, October 24, 2009 - 5:37 am UTC

Hi Tom,

http://asktom.oracle.com/~tkyte/Misc/NLSDateFormat.html This URL is not accessible .. will you please check this ?

Not Found
The requested URL /~tkyte/Misc/NLSDateFormat.html was not found on this server.

Regards

Bala
Tom Kyte
October 26, 2009 - 1:56 pm UTC

please see the home page for the new base link to that content, I had to move it and change URLS

select TO_CHAR(ROUND(SYSDATE, 'D')) from dual; gives different Output in sql*plus and sqlplus

Gaurav Jain, November 04, 2009 - 5:47 am UTC

Today is 04-Nov-2009 and I tried to run this query:
"select TO_CHAR(ROUND(SYSDATE, 'D')) from dual;" 
on my database server and here it is giving output as :

COREACC> select TO_CHAR(ROUND(SYSDATE, 'D')) from dual;

TO_CHAR(R
---------
01-NOV-09


And again I tried same query from sql*plus on same database with same user and here it gives output something like this:

SQL> select to_char(trunc(sysdate,'D')) from dual;

TO_CHAR(T
---------
02-NOV-09


could you please elabourate this issue , is it the issue of Oracle or Interface? my sql*plus version is :

Connected to:
Oracle9i Enterprise Edition Release 9.0.1.3.0 - 64bit Production
With the Partitioning option
JServer Release 9.0.1.3.0 - Production


Thanks in Advance,
Gaurav Jain

Tom Kyte
November 09, 2009 - 3:44 pm UTC

what is the difference between sqlplus and sql*plus?

In any case, the time comes from the operating system. It would have been *interesting* to see sysdate with the date and time output.


The operating returns the time obeying the TZ (timezone) settings in place. You could get at least three different dates easily from the database. Suppose the database was started with TZ=est. If the database starts your server process (eg: a shared server), it would return sysdate relative to est.

Suppose your listener was started with a TZ of cst. Any dedicated server it starts would have TZ=cst and the time relative to that.

Suppose you log into the machine directly and use sqlplus without the network (no listener, dedicated server). Then, you would be supplying the TZ value and it could be different.

<b>
[tkyte@dellpe ~]$ export TZ=EST
[tkyte@dellpe ~]$ date
Mon Nov  9 16:43:26 EST 2009
</b>[tkyte@dellpe ~]$ plus

SQL*Plus: Release 10.2.0.4.0 - Production on Mon Nov 9 16:43:28 2009

Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

ops$tkyte%ORA10GR2> select to_char(sysdate,'dd-mon-yyyy hh24:mi:ss' ) from dual;

TO_CHAR(SYSDATE,'DD-
--------------------
<b>09-nov-2009 16:43:35
</b>
ops$tkyte%ORA10GR2> exit
Disconnected from Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
<b>[tkyte@dellpe ~]$ export TZ=PST
[tkyte@dellpe ~]$ date
Mon Nov  9 21:43:42 PST 2009
</b>[tkyte@dellpe ~]$ plus

SQL*Plus: Release 10.2.0.4.0 - Production on Mon Nov 9 21:43:44 2009

Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

ops$tkyte%ORA10GR2> select to_char(sysdate,'dd-mon-yyyy hh24:mi:ss' ) from dual;

TO_CHAR(SYSDATE,'DD-
--------------------
<b>09-nov-2009 21:43:45</b>




so, I suspect you have environmental differences in your different environments.

A Default Date returns an ORA-1843

Suzanne, July 07, 2010 - 5:58 pm UTC

I've read through this thread and I understand now how a date can be invalid on some clients and not on others but I'm still confused about why a table (created long ago) with a default date would return an ORA-1843 on an INSERT statement without the date specifically called out.

I'm running Oracle 11.2 and the database is on a Linux server. My clients are a mix of Sun Solaris and Windows. The table create looks like this -
CREATE TABLE CD_THIRD_PARTY_INFO
(
TCSI_OFFICE_ID VARCHAR2(15) NOT NULL,
THIRD_PARTY_INFO NUMBER(*,0) DEFAULT 0 NOT NULL,
CREDIT_SCORE NUMBER(*,0) DEFAULT -1 NOT NULL,
CREDIT_SCORE_DATE DATE DEFAULT '01/01/70 00:00:00' NOT NULL,
TRANSCREDIT_DTP NUMBER(*,0) DEFAULT -1 NOT NULL,
PURE_CREDIT_SCORE NUMBER(*,0) DEFAULT -1 NOT NULL,
RIVIERA_ID VARCHAR2(50) NULL,
TIA_ID VARCHAR2(15) NULL,
RMIS_ID NUMBER(*,0) NULL,
CLIENTSCARRIERID VARCHAR2(15) NULL,
CARGO_STATUS VARCHAR2(25) NULL,
MONITORED CHAR(1) DEFAULT 'U' NULL,
UPDATED_MONITORING_BY VARCHAR2(25) DEFAULT 'System' NOT NULL,
MONITORING_UPDATED DATE DEFAULT SYSDATE NOT NULL,
ADMIN_NOTES VARCHAR2(1000) NULL,
P3_LEVEL NUMBER(*,0) DEFAULT 0 NULL,
CONSTRAINT CK_MONITORED
CHECK (MONITORED in ('M','N','U','F'))
)

This INSERT statement returns an ORA-1843
insert into cd_third_party_info (tcsi_office_id, admin_notes) values ('S.1234.00', 'this is a test')

Doesn't the default date get resolved at the server level?
Tom Kyte
July 08, 2010 - 12:17 pm UTC

got any triggers on that table, show us a cut and paste from sqlplus directly please.

ORA-1843 on an Insert

Suzanne, July 08, 2010 - 1:26 pm UTC

The CREATE command I included is the exact command I used to create my test table.  There aren't any triggers, indexes or foreign keys on this table.  I made it as vanilla as I could.

Here is the SQL Plus of my INSERT -

SQL> insert into cd_third_party_info (tcsi_office_id, admin_notes) values ('S.1234.00', 'this is a 
  2  test')
  3  ;
insert into cd_third_party_info (tcsi_office_id, admin_notes) values ('S.1234.00', 'this is a
*
ERROR at line 1:
ORA-01843: not a valid month

I forgot to include two pieces of information, first the database has the NLS_DATE_FORMAT set to MM/DD/RR HH24:Mi:SS
Secondly, my developer fixed the ORA-01843 by doing this -

alter table CD_THIRD_PARTY_INFO modify (credit_score_date default to_date('01/01/1970','mm/dd/yyyy'));

As a DBA I'm interested in knowing why Oracle is having this issue in the first place.

Tom Kyte
July 08, 2010 - 1:49 pm UTC

oh, I see it now


CREDIT_SCORE_DATE DATE DEFAULT '01/01/70 00:00:00' NOT NULL,



you are using a string as a default for a date, it would use the default NLS settings to convert that string into a date upon insert. The default is really:


to_date( '01/01/70 00:00:00' )

not just the string (there is an IMPLICIT conversion there). That is the cause.

The developer just did what they should have done from the get go - use an explicit date mask and do not allow implicit conversions to take place.

ORA-01843 on a default date

Suzanne, July 09, 2010 - 11:22 am UTC

So just to make sure I have this correct - the default date because it is a string does an implicit to_date conversion and since the client NLS_LANG and the server NLS_LANG don't match the client NLS settings are the settings used in resolving the to_date parameters which in this case would be the date format. Do I have this right?
Tom Kyte
July 09, 2010 - 5:03 pm UTC

it has nothing to do with a client NLS_LANG and server NLS_LANG

it has everything to do with the sessions current nls-date-format and the fact that the string that the date defaults to does NOT convert with the current session nls-date-format.


implicit conversions are evil. I wish they were illegal (too late now, we cannot make them illegal - pretty much 99.9999% of existing code would cease to compile).

watch:


ops$tkyte%ORA11G> alter session set nls_date_format = 'dd-mm-yy';

Session altered.

ops$tkyte%ORA11G> create table t ( a int, b date default '01-02-03' );

Table created.

ops$tkyte%ORA11G> insert into t (a) values  (1);

1 row created.

ops$tkyte%ORA11G> alter session set nls_date_format = 'dd-yy-mm';

Session altered.

ops$tkyte%ORA11G> insert into t (a) values  (2);

1 row created.

ops$tkyte%ORA11G> alter session set nls_date_format = 'yy-mm-dd';

Session altered.

ops$tkyte%ORA11G> insert into t (a) values  (3);

1 row created.

ops$tkyte%ORA11G> alter session set nls_date_format = 'yy-dd-mm';

Session altered.

ops$tkyte%ORA11G>
ops$tkyte%ORA11G> alter session set nls_date_format = '"day=" dd "mon=" mon "year = " yyyy';

Session altered.

ops$tkyte%ORA11G> select * from t;

         A B
---------- -----------------------------
         1 day= 01 mon= feb year =  2003
         2 day= 01 mon= mar year =  2002
         3 day= 03 mon= feb year =  2001




if you see a date set to/compared to a string - scream at them (those that did that)

if you see a to_date WITHOUT a format - scream at them (those that did that)

if you see a to_char of a date WITHOUT a format - scream yet again


TimesTen DATE constant

Bob Lyon, September 09, 2010 - 2:30 pm UTC

Hey Tom,

There IS someting new every day!
these TimesTen constructs (DATE, INFINITE and NAN) are apparently in Oracle's core
(but are only documented in the TimeTen manuals)


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
With the Partitioning, Data Mining and Real Application Testing options


ADM_BDLYON> SELECT *
2 FROM (SELECT DATE '2010-01-01' whence
3 ,'123' ba
4 FROM DUAL)
5 WHERE ROWNUM IS NOT INFINITE
6 AND ba_no IS NOT NAN
7 /

WHENCE BA
----------------- ---
01/01/10 00:00:00 123

1 row selected.


I was browsing V$SQL and saw a query using the "SELECT DATE 'YYYY-MM-DD'" construct and about fell out of my chair!

Link

Tarun Narula, September 11, 2010 - 5:03 pm UTC

Hi Tom,

Second link is broken...
Regards,

not broken ...

Sokrates, September 13, 2010 - 10:26 am UTC

is too!

Duke Ganote, September 13, 2010 - 4:00 pm UTC

The link didn't work for me... the mysteries of HTML, I suppose.

BTW, the ANSI DATE is a wonder; I asked about it last year:
http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:2076092100346846217

ALTER SESSION SET nls_date_format

Pratibha, September 24, 2012 - 12:41 pm UTC

l_xml_dformat := 'YYYY-MM-DD"T"HH24:MI:SS';

EXECUTE IMMEDIATE 'ALTER SESSION SET nls_date_format = ''' || l_xml_dformat || '''';


what is the use of T in 'YYYY-MM-DD"T"HH24:MI:SS'. I read somewhere it is just a seperator between date and time. But, My date now renders a T in between. eg, 2012-01-01T00:00:00

What is the use of T here....
Tom Kyte
September 27, 2012 - 8:13 am UTC

probably because of this

http://en.wikipedia.org/wiki/ISO_8601

an ISO standard format

Date Validation issue with NLS_CALENDAR = 'Arabic Hijrah'

Sridhar, September 06, 2013 - 4:55 am UTC

Hi Tom,
We are building a small webpage where a person can enter personal information and Date of Birth is one among them. Since this page is for Saudi, we had to build a page where he can pick Arabic Hijrah Calendar dates. So there are basically 3 fields (2 drop downs, one for day and one for month, and one text field where he can enter the year). When submitting I will concatenate those fields, use the TO_DATE function to change the Hijrah Calendar dates to Gregorian and store them in a table. Now the issue I am facing is if I enter a invalid Hijrah Calendar date, Oracle is not validating it:

Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production
PL/SQL Release 11.1.0.7.0 - Production
CORE 11.1.0.7.0 Production
TNS for 64-bit Windows: Version 11.1.0.7.0 - Production
NLSRTL Version 11.1.0.7.0 - Production

If we enter a wrong date in Gregorian, it prompts ORA-01839:

scott@SRID> select to_char(to_date('31092010','ddmmyyyy','nls_calendar=''gregorian'''),'dd-mon-rrrr','nls_calendar=''gregorian''') from dual;
select to_char(to_date('31092010','ddmmyyyy','nls_calendar=''gregorian'''),'dd-mon-rrrr','nls_calendar=''gregorian''') from dual
                       *
ERROR at line 1:
ORA-01839: date not valid for month specified


But if we enter a wrong date in Arabic/English Hijrah, it simply shows the next valid date:

scott@SRID> select to_char(to_date('31091410','ddmmyyyy','nls_calendar=''english hijrah'''),'dd-mon-rrrr','nls_calendar=''english hijrah''') from dual;

TO_CHAR(TO_DATE('31091410','DDMMYYYY','NLS_CALENDAR=''ENGLISHHIJRAH'''),'DD-MON-RRRR','NLS_CALENDAR=
----------------------------------------------------------------------------------------------------
01-Shawwal          -1410

Please note that there is no 31st day in any of the Arabic Calendar months.
Is this a bug or intended behavior.
Many thanks in advance.


Tom Kyte
September 09, 2013 - 11:29 am UTC

sorry, i don't know enough about arabic calendaring to answer this, please utilize support

Yattu, January 25, 2019 - 9:13 am UTC

I getting the following error ora-08186 invalid timestamp specified.

And I also check on the net but some blog says set to set NLS_DATE_FORMAT so I also set the parameter but still I get the same error.

Here I post my NLS_* parameter as below.

NAME VALUE
nls_language AMERICAN
nls_territory AMERICA
nls_sort BINARY
nls_date_language AMERICAN
nls_date_format DD-MON-RR
nls_currency $
nls_numeric_characters .,
nls_iso_currency AMERICA
nls_calendar GREGORIAN
nls_time_format HH.MI.SSXFF AM
nls_timestamp_format DD-MON-RR HH.MI.SSXFF AM
nls_time_tz_format HH.MI.SSXFF AM TZR
nls_timestamp_tz_format DD-MON-RR HH.MI.SSXFF AM TZR
nls_dual_currency $
nls_comp BINARY
nls_length_semantics BYTE
nls_nchar_conv_excp FALSE
Connor McDonald
January 28, 2019 - 3:32 pm UTC

"I getting the following error ora-08186 invalid timestamp specified"

When? How? You need to show us what you are running

custom settings cause function to not work properly

Durga, May 23, 2019 - 6:36 am UTC

Hi Connor,

I have the following issue -

When custom date/time settings are used this function doesn't work.

------ Custom connection setting -------------
SET numformat 999999999999999999;
SET numwidth 20
alter session set nls_date_format = 'DD-MON-YY HH24:MI:SS';
----- end of custom connection setting -----------
Example: This fails and is off by 100 years.
select HERTZDATE_2_TERMDATESTRING(18217) from dual;
returns 11/17/2119
correct answer is: 11/16/2019


With connection defaults, this function works:
select HERTZDATE_2_TERMDATESTRING(18217) from dual;
returns:
11/16/2019

Please advice

Chris Saxon
May 24, 2019 - 8:43 am UTC

You're going to have to share the code for the HERTZDATE_2_TERMDATESTRING function.

Because I don't understand how the number 18217 maps to the date 16 Nov 2019.

custom settings cause function to not work properly

Durga, May 27, 2019 - 8:27 am UTC

Hi Chris,

Please find the 2 functions below:

create or replace FUNCTION "HERTZDATE_2_TERMDATESTRING"
(i_hertzdate in number)
RETURN VARCHAR2 AS

v_oracledate date;

BEGIN
if (i_hertzdate = 99999) then
return 'Blank';
else
v_oracledate := hertzdate_2_oracledate(i_hertzdate);
return to_char(v_oracledate, 'MM/DD/YYYY');
end if;
END;

--------------------------------------------------------

create or replace FUNCTION HERTZDATE_2_ORACLEDATE
(i_date IN INTEGER)
RETURN DATE

AS
v_UnixDateEpoch DATE := To_Date('31-Dec-69');
v_RtnDate DATE := v_UnixDateEpoch + i_date;
BEGIN
RETURN v_RtnDate;
END;


Please advice
Connor McDonald
May 29, 2019 - 6:21 am UTC

You need to use RR if you want a 2 digit year to be century-intelligent, otherwise this happens:

SQL> alter session set nls_date_format = 'DD-MON-YY HH24:MI:SS';

Session altered.

SQL> select  To_Date('31-Dec-69') from dual;

TO_DATE('31-DEC-69
------------------
31-DEC-69 00:00:00

SQL> select  to_char(To_Date('31-Dec-69'),'dd-mon-yyyy') from dual;

TO_CHAR(TO_DATE('31-
--------------------
31-dec-2069


More to Explore

VLDB

If you are new to partitioning, check out Connor McDonald's introduction series here.

VLDB

Documentation set on VLDB and Partitioning.