using oracle to_date function without a format mask - oracle

this may be a dumb question however.. I have these two selects: 1st one returns a result, while 2nd gives me a not a valid month error. I can't seem to figure out why..
select to_date('09-12-14','dd-mm-rr') - to_date('01/january/2007') from dual;
select to_date('09-12-14','dd-mm-rr') - to_date('01-01-2007') from dual;
Tnx in advance

When you don't specify a format mask, Oracle will use the NLS_DATE_FORMAT setting (and some predefined masks) to determine the date time format mask.
Apparently your server settings support the first format, and not the second. Therefore it is better to always specify your format mask.

Related

How to Insert a Timestamp in Oracle in a Specific Format

I am at a loss as how to insert the current time in a different format than the default. Can somebody help explain?
Here is how my table was created:
CREATE TABLE ACTIVITY_LOG
(
TIME TIMESTAMP NOT NULL
, ACTIVITY VARCHAR2(200) NOT NULL
);
My insert command works:
insert into activity_log
values (localtimestamp,'blah');
But how do i insert the localtimestamp value into my table in a different format using the various MM DD YY HH MM SS tags? I've tried the following, but it gives me the ORA-1830: date format picture ends before converting entire input string error.
insert into activity_log
values (to_timestamp(localtimestamp,'YYYY/MM/DD'),'blah');
You don't insert a timestamp in a particular format. Timestamps (and dates) are stored in the database using an internal representation, which is betwen 7 and 11 bytes depending on the type and precision. There is more about that in this question, among others.
Your client or application decides how to display the value in a human-readable string form.
When you do:
to_timestamp(localtimestamp,'YYYY/MM/DD')
you are implicitly converting the localtimestamp to a string, using your session's NLS settings, and then converting it back to a timestamp. That may incidentally change the value - losing precision - but won't change how the value is stored internally. In your case the mismatch between the NLS setting and the format you are supplying is leading to an ORA-01830 error.
So your first insert is correct (assuming you really want the session time, not the server time). If you want to see the stored values in a particular format then either change your client session's NLS settings, or preferably format it explicitly when you query it, e.g.:
select to_char(time, 'YYYY-MM-DD HH24:MI:SS.FF3') from activity_log
You don't seem to provide any indication of what your 'localtimestamp' is - is that pseudocode? A variable name? A column you haven't shown the definition for?
What data type is 'localtimestamp'? What data does it contain? Pertinent questions as other answers point out, because if it truly is a time stamp then oracle will be converting it to a string for you, before passing that string to to_timestamp() in your final query. Your initial stab at it should just work if the variable is a timestamp, containing a timestamp
Ultimately "date format picture ends" means "you passed me a string looking like '2017-05-17 12:45:59', but claimed it was only 'yyyy-mm-dd'. What was I expected to do with the rest of it?"
Your current final comment on your question "I was hoping to look in the table and see a useful looking time" - that's your query tool's problem. Have a look in the setting of your query tool and change the date format it displays. As has been noted, dates in oracle are stored as a decimal number days since a certain moment in time. If 0 represents 01 Jan 1970, then 1.75 represents 6pm on the 2 Jan 1970. It is up to the end program the user is using, to format the date into something you like.. you cannot "insert a timestamp with a different format" because time stamps don't have a format any more than a number like 1.75 has a format. It is what your query does with it when it gets it out, that gives it the format:
To_char(timestampcol, 'yyyy mm did')
To-char(tomestampcol, 'mon dd yyyy')
These use oracles built in date formatter, that turns that decimal number of the date into a string in the given format; you will see a string.. or you can just write "select * from table" and run it in TOAD and toad will show you the dates according to the format in settings, or you can write a c# program and get a load of date objects out and call my date.ToString("yyyy-MM-dd") on them to format them. The idea I'm trying to get across is that you don't pick the date format on the way in, you pick it on the way out, if you don't like what you're looking at, you have to change it on the way out, not the way in

change date format 'yyyy/mm/dd' to 'mm-dd-yyyy' in Oracle

I have inserted into a table in Oracle. My implementation without PLSQL would be:
SELECT to_date('1900-01-01','YYYY-MM-DD') + (rownum - 1) AS DT_CAL,
rownum AS NUM_JOUR
FROM dual
CONNECT BY to_date('1900-01-01','YYYY-MM-DD') + (rownum - 1) <=
to_date('2000-12-31','YYYY-MM-DD')
result is: 05/28/1900, not 1900-05-28. Can you help me understand what the problem is?
The DATE data type does not have a format; Oracle stores it as either 7- or 8-bytes and it is not until it is passed to a client program (i.e. SQL/Plus, SQL Developer, Toad, Java, Python, etc) and that client program formats it according to whatever rules it has that the date gets a format.
If you are using SQL/Plus or SQL Developer then it will use the NLS_DATE_FORMAT session parameter to format the date. You can change this using:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
(Be aware that this will only change the format in the current session and will not change it for any other sessions/users.)
If you want to give the date a particular format then you will need to convert it to a string.
to_date() takes your string parameter, matches it to the format you provide in the second parameter, and constructs a date field from it. The date field isn't using the format you provided in the second parameter - in fact it'll be stored using some internal data representation that has no format at all (a number, in all likelihood).
To present a format back out in the results from a date field, you can either:
Have the client executing the query set the NLS parameters (at session level) to provide a localized format, with an ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD'; statement), or
Use to_char(..., 'YYYY-MM-DD') around your existing field to turn the date back into a string formatted the way you want to have it. Where you replace ... with your current column definition in the select.
Approach #1 is already happening, as there'll already be an NLS_DATE_FORMAT set that is producing the current format, but it's with a format you don't want, so if you can control it and change it there, you can do it that way. If you can't and you must have the format a single consistent other way, then #2 could be the way to go.

Oracle to_date format issue

I have an insert statement, where one of the inserted fields is date. I use to_date function to convert string to date in this way:
to_date('10-MAY-10', 'DD-MON-RR')
It works fine, but I found, that it allows also variants like:
to_date('10?MAY?10', 'DD-MON-RR')
to_date('10+MAY+10', 'DD-MON-RR')
I'm expecting an Oracle error, however it makes an insert. Could you please explain why or give a reference to relevant documentation?
Oracle will test for other formats if it fails to find a match in the string - you can see the rules for what it looks for here in the documentation.
As an aside, years have four digits. Please make sure you specify all four when you provide a date-as-a-string, where possible; it saves the database from having to guess and potentially getting it wrong. I.e. your original example should be:
to_date('10-05-2010', 'DD-MM-YYYY')
If you need to restrict the date-as-a-string to a specific format, you can use the fx format modifier, which is mentioned earlier in the same document I linked to previously.
eg. to_date('10/05/2010', 'dd-mm-yyyy') would match but to_date('10/05/2010', 'fxdd-mm-yyyy') would fail

date format with inconsistant data Oracle SQL

I am have a freetext column which a date is input to.
is there a way i can force the output to display the same?
for example some people are entering '2/12/15' others are entering '02/12/2015'
how i can i get the output to pick up the dates and change them to a consistant format?
no idea where to start. I have tried "To_char" but it says 'invalid number'
Actually I believe you want to_date( ):
select to_date('2/12/15', 'mm/dd/rrrr')
from dual;
The 'rrrr' for year will format the year correctly. See date formats here: https://docs.oracle.com/cd/B28359_01/server.111/b28286/sql_elements004.htm
Your best approach here may be to use a PL/SQL function that accepts the string and then attempts a series of date conversions on it with different date format pictures ('DD/MM/YY', 'DD/MM/YYYY' etc) until it finds one that does not raise an exception.
This won't work if some people enter DD/MM/YYYY and others enter MM/DD/YYYY, but will appear to in some cases.

Oracle to_date procedure with different results

I'm calling an Oracle procedure with this code:
begin
PPT2000_AGG_HOURLY.RUNDURATION_HOURLY(4, to_date('01112014', 'DDMMYYYY'), 20);
end;
/
My problem is the date format. On one PC the procedure calculates all fine with the result for the date 01.11.2014 00:00.
On the other PC (same version of Oracle SQL Developer) the procedure returns
0 for the calculation and for the date 01.11.2014
So something seems to be different in converting the date and I don't know why. I tried it with a third PC and get also the return of 01.11.2014.
The PC which gives the correct result has the same operating system (WIN7 German) and the same version of the Oracle SQL Developer. Also the same Oracle database.
So how could this be possible?
Update Solution:
Thanks for the answers, I changed the NLS-Settings from DD.MM.RR to DD.MM.RR HH24:MI and now it works :)
You should handle the display format in the code, and not depend on the client's NLS_DATE_FORMAT. You can't expect 1000 users to change their local NLS settings in their GUI based client tools.
A date doesn't have a format. What you see, is just for display depending on the locale-specific NLS_DATE_FORMAT of the client.
And the NLS_DATE_FORMAT could be overridden at different levels. If you don't want to depend on the client's NLS settings, then always use TO_CHAR with desired format mask to make sure it is overridden at individual statement level.
Remember, for diaplaying DATE values, always use TO_CHAR with desired format. To do date arithmetic, use TO_DATE to convert a literal into DATE.
For example,
TO_CHAR(date_column, '<desired_format>')
It will override the locale-specific NLS_DATE_FORMAT at statement level.
See this similar answer for more understanding.
If you really have a constant date then use the Oracle DateTime literal. It works every time and it's independent of the NLS_DATE_FORMAT:
begin
PPT2000_AGG_HOURLY.RUNDURATION_HOURLY(4, DATE '2014-11-01', 20);
end;
/
Check the NLS preferences in SQL Developer to see if there is a mismatch. Go to Preferences->Database->NLS. You can also override these settings on a per session basis if you want.

Resources