How do we set the data format for a database
A reader, September 23, 2001 - 1:05 pm UTC
and
the scripts which you write , return date with time as well by deafault , how is that made possible.
September 23, 2001 - 1:45 pm UTC
I either use to_char( dt_field, 'dd-mon-yyyy hh24:mi:ss' )
or I've issued:
alter session set nls_date_format = 'dd-mon-yyyy hh24:mi:ss';
in my session before selecting a date.
A reader, July 09, 2003 - 9:13 pm UTC
Hi Tom,
I have a procedure that fetchs data from a cursor in which one of its columns is a varchar2(9) datatype, which contains values in the format 'dd-mon-yy' or the word 'null'.
The default value for the parameter nls_date_format is 'dd-mon-rr'
If I set nls_date_format to 'mm/dd/yyyy' on a sql*plus session and then run the procedure, I get an error 6502 PL/SQL: numeric or value error, when the cursor tries to fetch values in the format 'dd-mon-yy'.
But If I leave the nls_date_format in its default value (dd-mon-rr) or if I set it to 'mm/dd/yy', the procedure runs without any problem on sql*plus for any kind of value ('dd-mon-yy' or the word null).
1-Can you tell me why I am getting this error if I change the nls_date_format to 'mm/dd/yyyy'?
2-Due to I have a mix of words and dates in a varchar2 datatype column, shouldn't I receive the error no matter what the setting is for the nls_Date_format parameter?
Thanks in advance for any help on this.
July 10, 2003 - 7:43 am UTC
1) because apparently you've done the worst thing you can do, you stored dates as strings -- meaning that all implicit conversions will be problematic performance wise and error wise forever.
In addition to storing a date in a string -- which is really bad -- you've forgotten that it takes a MINIMUM of 4 characters to store a century/year. Tell me, what is 12-jan-40. ugh.
create the view as
select ...., decode( c, 'null', to_date(null), to_date(c,'dd-mon-rr') ) c
and that'll solve your implicit conversion problem -- but not your "i've no idea what year this data is really for" problem.
2) no, the date formats are forgiving in that fashion to a point. But that also points out why you never never (as in never) want to rely on implicit conversions. what if someone sticks in 01-11-10 is that the 1st of november 2010, the 11th of jan 1910, what?
what do you recommend
dwl, March 03, 2004 - 6:54 am UTC
So i am just wondering what you believe is best practice for writing code in applications (apart from moving all the sql into the database!)??
If we have a java app using jdbc to oracle 8.1.7.4.
1) Then should any sql that references and compares dates in the app code, do an explicit TO_DATE on each date??
ie WHERE mydatefield = TO_DATE('01/01/2001', 'DD/MM/RRRR');
Obviously this makes a call to the TO_DATE function, so is this the most efficient way i.e. more efficient than forcing all jdbc clients to use a certain nls_date_format eg using a logon trigger or env variable and then coding eg:
WHERE mydatefield = '01/01/2001';
ie no call to TO_DATE. or is this so neglible that i shouldn't worry about it? I'm mainly thinking about some app which may run some sql code hundreds or thousands of times a day, so calling TO_DATE a lot!
2) If the client either odbc or jdbc connects to the database without any registry settings or environmental settings for nls_date_format, then which format would it pick up, the nls_instance_parameter settings??
What if NLS_LANG is set in the registry but not the nls_date_format??
3) How can i use sqlplus to emulate the jdbc/odbc clients. ie i want to test some sql using the same nls settings that the client would use. At the moment i issues an explicit allter session set nls_date_format in my glogin.sql script but if i want sqlplus to use the nls_instance_parameters what should i do, delete the glogin script??
Thanks for your help.
March 03, 2004 - 9:59 am UTC
1) yes, use to_date. else you introduce unavoidable ambiguities into the code.
2) odbc is almost always on windows, windows ALWAYS has registry settings. The problem is some clients will get it from the db, some from the client, some set on their own -- you cannot control it. that is why i like #1
3) yes, just don't alter and sqlplus will do what the client would do.
April 2005 has more than 30 days ;-)
A reader, April 28, 2005 - 12:34 pm UTC
SQL>select to_char(sysdate,'day dddth month yyyy') from dual;
TO_CHAR(SYSDATE,'DAYDDDTHMONTH
------------------------------
thursday 118th april 2005
SQL>select to_char(sysdate,'day ddddth month yyyy') from dual;
TO_CHAR(SYSDATE,'DAYDDDDTHMONTH
-------------------------------
thursday 1185th april 2005
Having a good laugh after a bad day :-)
date query
ian gallacher, September 17, 2005 - 4:15 pm UTC
Hi
Have always had problems with dates in my app since (rightly or wrongly) the app passes parameters from one form to another via globals! This give me a headache since dates are passed in this manner and thus become character strings giving problems especially when using DDMMYY. I get round this be using some sql to make sure I am getting the correct century. However I have noticed a peculiarity with the year 50 !
My code :-
/* forgot problem with using 6 digit dates
if key in 010150 routine comes back with 01012050
if key in 311249 routine comes back with 31121949
*/
BEGIN
/* will decode DDMMYY DDMMYYYY */
select
to_date(to_char(to_date(ON_SET,'ddmmrrrr'),'ddmmrrrr'),'ddmmrrrr')
into CHECK_DATE
from dual;
if check_date is not null then
if check_date > sysdate then
check_date := add_months(check_date,-100*12);
end if;
D_DATE := to_char(CHECK_DATE,'DD/MM/YYYY 00:00:00');
return;
end if;
exception when others then null;
END;
What is special for 50 to Oracle ?
Have also hit problems when using dates > year 2050 !
Any comments would be appreciated
Thanks
September 17, 2005 - 11:47 pm UTC
you are using the rr format - have you read about the rr format.
YY would say "just take what you got and use it", if you give me 50 and the year is 2005 - we'll have 2050. If you give me 50 and the year is 1999, we'll have 1950 -- we'll use the century from the current year.
RR creates a window of plus or minus 50 years from the current century (1950ish-2050ish). In 1999 and 2005 - the year "50" is the same thing.
You have a pretty serious BUG in your application - it uses two characters where ONLY FOUR can work.
You don't have problems with years > 2050, you have *ambiguity* - you don't *know* because someone won't tell you.
problem with date formats
ian gallacher, September 18, 2005 - 9:47 am UTC
Hi
Thanks for your response
Just a follow up on my BUG !
Dates are entered into my via forms using ddmmrr after 2000
Prior to that were using ddmmyy
Transaction dates started around 1993/94
Date mask of dd/mm/yyyy is used for Dates of Birth
Only time hit a bit of hassle is when date is passed to a global or entered into a char field
Current example are when dates are entered into character fields when an exact date is not known date of onset of clinical condition
i.e may-1994, 1955, 01/01/1994, 01011994, 01/01/93,12/94 etc which is more of a narrative than proper dates
Do you think sql for processing global dates in previous post handles dates ok from 1990 - future ?
Thanks
September 18, 2005 - 11:30 am UTC
Only you can answer that last question, does it meet your end users expected outcome
And are your end users willing to live with the fact that what they typed in might not be what gets stored since you lose the century and have to put it back later and can only "guess" what the most likely century is?
I'd look at this as a "priority 1++ bug" and acutally fixed the underlying cause - find the globals and have them store the data in a lossless format.
Can SQL call a function within a "C" DLL file??
Thom, April 01, 2006 - 12:09 am UTC
Does anyone know how to call a function from within SQL?? Hum? If you can call a "C" DLL function within an SQL program, Please let me now how! I might be able to offer a solution on all your mentioned date format problems.
Thom.
April 01, 2006 - 9:53 am UTC
yes you can (we call them external procedures) but trust me - if you can "fix" this in C, we can do it in PLSQL just as easily.
So, tell us the algorithm you would use to "fix" this :)
problem with NLS_DATE_FORMAT resolution
olivier, June 21, 2007 - 11:01 am UTC
Tom,
I have a problem with related to dates conversions with a software package working on oracle 9.2.0.6.0 : after working fine for a while, some process start crashing all the time because of date conversions issues (there are implicit conversions somewhere in the code).
After some investigation, we found out that oracle seems not to resolve the right NLS_DATE_FORMAT parameter. I mean it uses the DATABASE level parameter instead of the SESSION level parameter set with an ALTER SESSION command :
Here is what i found :
SELECT * FROM NLS_DATABASE_PARAMETERS where parameter = 'NLS_DATE_FORMAT';
---------------------------------------------
PARAMETER VALUE
NLS_DATE_FORMAT DD-MON-RR
SELECT * FROM NLS_SESSION_PARAMETERS where parameter = 'NLS_DATE_FORMAT';
---------------------------------------------
PARAMETER VALUE
YYYYMMDD:HH24MISS 21-JUN-07
Select sysdate from dual;
---------------------------------------------
Sysdate
21-JUN-07
As you can see, the default date format defers from the session level NLS_DATE_FORMAT.
I saw on some website that there could be a bug for the format resolution on oracle 7xxxx, but nothing about it for later versions of oracle.
What do you think ?
Regards,
Olivier
June 21, 2007 - 11:20 am UTC
I think I would like to see an entire test case with the necessary steps to see what you see.
ORA-01858
yasser, April 24, 2020 - 8:32 am UTC
Hi there,
I have this inserting query in Proc program :
INSERT INTO ORDER (DATEORDER)
VALUES (to_date(decode(:ecddenlev,'-1',null,:ecddenlev),'DD/MM/RR HH24:MI')).
And also, I have the variable :ecddenlev = '-1'.
When I launch the Proc program, I receive this error message :
ORA-01858: a non-numeric character was found where a numeric was expected.
Any Idea please.
Thanks in advance.
Best Regards
Yasser
April 27, 2020 - 4:14 pm UTC
What's the full code that runs this SQL?
Appear to be a data issue...
J. Laurindo Chiappa, April 27, 2020 - 6:40 pm UTC
Could be some issue wuth your data - please make SURE the bind variable ecddenlev REALLY is a string and it contains OR '-1', without ANY spaces or any extra characters, OR it contains a VALID data string in the given format... Example :
SYSTEM@O11GR2:SQL> create table ORDER (DATEORDER date);
Table created.
SYSTEM@O11GR2:SQL> variable ecddenlev varchar2(40);
SYSTEM@O11GR2:SQL> exec :ecddenlev := '-1';
PL/SQL procedure successfully completed.
SYSTEM@O11GR2:SQL> print ecddenlev
ECDDENLEV
--------------------------------------------------------------------------------------------------------------------------------
-1
==> Now I try your code :
SYSTEM@O11GR2:SQL> Begin
2 INSERT INTO ORDER (DATEORDER)
3 VALUES (to_date(decode(:ecddenlev,'-1',null,:ecddenlev),'DD/MM/RR HH24:MI'));
4 END;
5 /
SYSTEM@O11GR2:SQL> select * from ORDER;
DATEORDE
--------
1 linha selecionada.
=> ok, a record with NULL date was inserted, as expected... Now let´s put a valid date string using the given format in the variable :
SYSTEM@O11GR2:SQL> exec :ecddenlev := '01/01/20 13:14';
PL/SQL procedure successfully completed.
SYSTEM@O11GR2:SQL> print ecddenlev
ECDDENLEV
--------------------------------------------------------------------------------------------------------------------------------
01/01/20 13:14
SYSTEM@O11GR2:SQL> Begin
2 INSERT INTO ORDER (DATEORDER)
3 VALUES (to_date(decode(:ecddenlev,'-1',null,:ecddenlev),'DD/MM/RR HH24:MI'));
4 END;
5 /
PL/SQL procedure successfully completed.
SYSTEM@O11GR2:SQL> select * from ORDER;
DATEORDE
--------
01/01/20
2 rows selected.
=> Now I will put an extra space in the -1 string :
SYSTEM@O11GR2:SQL> exec :ecddenlev := '-1 ';
PL/SQL procedure successfully completed.
=> As expected, I got an conversion error because the DECODE tried to pass the string to the TO_DATE function :
SYSTEM@O11GR2:SQL> Begin
2 INSERT INTO ORDER (DATEORDER)
3 VALUES (to_date(decode(:ecddenlev,'-1',null,:ecddenlev),'DD/MM/RR HH24:MI'));
4 END;
5 /
BEGIN
*
ERROR at line 1:
ORA-01847: day of month must be between 1 and last day of month
ORA-06512: at line 2
SYSTEM@O11GR2:SQL>
=> So, my first react is : CONFIRM that in your proc the variable ecddenlev REALLY is a string AND it contains '-1', without ANY spaces or any extra characters, OR it contains a VALID data string in the given format...
Regards,
Chiappa
Just to add....
J. Laurindo Chiappa, April 27, 2020 - 10:06 pm UTC
For an Example with the bind variable containing a date string in incorrect format, see :
SYSTEM@O11GR2:SQL> exec :ecddenlev := 'may/05/2020 14:00 ';
PL/SQL procedure successfully completed.
SYSTEM@O11GR2:SQL> print ecddenlev
ECDDENLEV
--------------------------------------------------------------------------------------------------------------------------------
may/05/2020 14:00
SYSTEM@O11GR2:SQL> ed
Wrote file afiedt.buf
1 Begin
2 INSERT INTO ORDERS (DATEORDER)
3 VALUES (to_date(decode(:ecddenlev,'-1',null,:ecddenlev),'DD/MM/RR HH24:MI'));
4* END;
SYSTEM@O11GR2:SQL> /
Begin
*
ERROR at line 1:
ORA-01858: a non-numeric character was found where a numeric was expected
ORA-06512: at line 2
SYSTEM@O11GR2:SQL>
We got the same error message reported by you, okdoc ?? Maybe this is your issue....
Regards,
Chiappa