TO_DATE problems - sql

I have the following in my SQL where clause. This is running against an Oracle database. The sc_dt field is defined in the db as a date field.
sc_dt = TO_DATE('2011-11-03 00:00:00.0', 'YYYY-MM-DD')
produces the following error "date format picture ends before converting entire input string"
When I try to account for the fractional seconds (.0 in this case) with the following, I get the following error.
sc_dt = TO_DATE('2011-11-03 00:00:00.0', 'YYYY-MM-DD HH24:MI:SS.FF')
produces the following error "date format not recognized"
I'm really just assuming that I need the .FF to account for the .0 in the "from" string. I've also tried .FF1, .FF2, ..., .FF9 with the same results (I'm grasping at straws at this point).
As far as I can see, the sc_dt field always has the month/day/year portion populated (and not the hour/minute/second portion).
I'm debugging a java program which is executing the above SQL as a prepared statement with the 2011-11-03 00:00:00.0 value.
How can I get around this?

You need to use the seconds past midnight option. Something like:
select TO_DATE('2011-11-03 00:00:01.1', 'YYYY-MM-DD HH24:MI:SS.SSSSS') from dual
Or This:
select TO_TIMESTAMP('2011-11-03 00:00:00.1', 'YYYY-MM-DD HH24:MI:SS.FF') from dual

An Oracle DATE column like sc_dt will always have a day and a time component down to the second. Depending on your query tool and how it is configured (generally the session's NLS_DATE_FORMAT), it is possible that the time component isn't being displayed by default. You can, however, see the time component by doing an explicit TO_CHAR
SELECT to_char( sc_dt, 'YYYY-MM-DD HH24:MI:SS' )
FROM table_name
Because a DATE only stores the time to the second, however, you cannot use fractional seconds in your format mask. So you would need to do something like this to extract just the portion of the string up to the fractional seconds. If you're not guaranteed that the string will always be 19 characters before the decimal point, you could use INSTR as well to look for the decimal point and take everything before that.
TO_DATE( substr('2011-11-03 00:00:00.0', 1, 19), 'YYYY-MM-DD HH24:MI:SS')
Since this is coming from a Java application, however, you're much better off using the correct data type. If you bind a Java date (java.sql.Date) using the setDate method on the prepared statement rather than binding a string, then you won't have to deal with the string format in your SQL statement.

I realize this thread is more than a year old but...
Another option just to throw it in might be:
src_dt=select TO_DATE('2011-11-03 00:00:01.1234', 'YYYY-MM-DD HH24:MI:SS.?????') from dual;
Note: there is an extra '?' thrown in to illustrate that you can even stick in a few extra '?'s. There is no complaint from Oracle if the digits represented by the '?'s do NOT have any corresponding character in the source time string. This might be helpful if you aren't sure of the precision of seconds you are receiving.
This option gives some flexibility to the format of "fractional seconds" from your source time.
I do not know that this is actually documented anywhere.

I did this :
ALTER SESSION
SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS.?';
--Change the decimal
ALTER SESSION
SET NLS_NUMERIC_CHARACTERS = ',.';
And it worked for me

src_dt=select TO_DATE('2011-11-03 00:00:01.1', 'YYYY-MM-DD HH24:MI:SS.SSSSS') from dual
I guess the above one should work if you just need a date output.

Related

How to insert date in SQL date type column?

I have a table with date type column.
I am trying to insert date in it:
But I get an error:
Please give me to make the correct query to put the date
Easy fix::
INSERT INTO t(dob) VALUES(DATE '2015-12-17');
Assuming this is an Oracle question based on the ORA-01843 error message, the problem appears to be in the date formatting as the error suggests.
In the provided example does the date '6-3-2012' mean '3 March 2012' or 'June 6, 2012?' The answer lies within the NLS_DATE_FORMAT parameter.
Out of the box, the Oracle date format is DD-MON-RR. So your corrected date format is either '03-MAR-12' or '06-JUN-12.' If the NLS_DATE_FORMAT has not been changed.
Never try to insert a string into a date column! If you have a string, use the to_date function with an explicit date format (and use 4 digit dates).
Relying on nls_date_format to implicitly convert your strings is just asking for trouble (like you just did), it can very easily change, even some apps will change it themselves.
The date literal (date '2015-12-17' https://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements003.htm#BABGIGCJ) always uses the same date format so that might be okay for ad hoc statements but you need to be aware that it is literal by name and literal by nature. They don't support bind variables so you will end up writing unshareable SQL to chew up your shared pool.

Oracle: One attribute with date, another with date and time?

I am taking an introductory course to databases so I am a complete beginner. In the database I am supposed to create I have two tables, each contain a DATE datatype.
In the first table, I want it to only display a date (DD-MM-YY) and in the second table display a date and time (DD-MM-YY HH24:MM).
How can I format each attribute to have these respective formats? I've looked around and tried the following command:
ALTER SESSION SET nls_date_format = 'YYYY-MM-DD HH24:MI:SS'
Which works nicely for the date and time field but leaves 00:00:00 for the date only field. Which I do not want, so I reverted it back to nls_date_format = 'DD-MM-YY'
As of right now the following:
INSERT INTO ITEM (ITEM_ENDDATEANDTIME)
VALUES ('13-AUG-13 23:56:00');
Gives me the error: date format picture ends before converting entire input string
Any ideas? Again, I'm a beginner a lot of this is new to me! Thanks!
What you want to do is always store your date values as dates. Data manipulation is infinitely easier when you have stored them in this format instead of in a text based format.
Then, you output them into a more human readable format through a query using syntax similar to this:
SELECT DateField,
TO_CHAR(DateField, 'YYYY-MM-DD HH24:MI:SS') AS Date1,
TO_CHAR(Datefield, 'DD-MM-YY') AS Date2
FROM MyTable
This takes the date data and outputs it as a formatted string. I hope this helps.

How can I convert a complex sysdate + something else with a to_date function?

Bit stuck here. Say I run the following SQL query:
select to_char(sysdate, 'DD/MON/YY') || ' 15:32:00' from dual;
The result gives me this:
08/NOV/12 15:32:00
Now I want to take that result and use it in a to_date function (long story as to why, but I'll go into detail in a sec):
select to_date((to_char(sysdate, 'DD/MON/YY') || ' 15:32:00'), 'DD/MON/YY HH24:MI:SS') from dual;
I was expecting the result to be the same as the previous one, except it isn't. Instead it gives me this:
08/NOV/12
Question is this: Is there a way I can use a concatenation of a to_char(sysdate, 'DD/MON/YY') and any combo of HH24:MI:SS in a to_date?
Additional detail that may or may not be of any additional use:
Reason I need to do this is because I was provided a query that has a table with an SLA time. The format is just a time in HH24:MI, however it's not a DATETIME type (I suspect it's a VARCHAR, but can't tell for sure as it's likely a view or function of some sort that I cannot dissect. Partially due to me not knowing how to and partially to me not having the necessary access due to my DB user.
EDIT: On reading the above again I realized I left out some additional detail (though this does not relate to my question at all I think):
I want to take today's date (DD/MON/YY), combine that with the SLA time of HH:MI, combine that with ':00' for :SS, convert the whole thing to a date, then do a comparison between the resultant abomination and the finish time for each row returned. If the finish time is bigger/ newer/ later than my combination-and-conversion-deluxe, then return something specific, in not, return something like "All OK". Not sure if that makes sense or not, but in summary, I want to get something that I can use to compare to another DATETIME type, so I think I need to somehow get the SLA time converted to a DATETIME type as well.
Any help on this will be greatly appreciated.
the output you see is converted to a char format. this is dictated by the NLS_DATE_FORMAT setting. internally, the date will still have the time format associated. so do this to see it:
SQL> select sysdate from dual;
SYSDATE
---------
08-NOV-12
SQL> alter session set nls_date_format='dd/MON/yy hh24:mi:ss';
Session altered.
SQL> select sysdate from dual;
SYSDATE
------------------
08/NOV/12 11:41:46
You're default date format is 'DD/MM/YY' If you want to display the time component you'll have to use the right date format:
select to_char(to_date((to_char(sysdate, 'DD/MON/YY') || ' 15:32:00'), 'DD/MON/YY HH24:MI:SS'),'DD/MM/YY HH24:MI:SS') from dual

In Oracle, convert number(5,10) to date

When ececute the following SQL syntax in Oracle, always not success, please help.
40284.3878935185 represents '2010-04-16 09:18:34', with microsecond.
an epoch date of 01 January 1900 (like Excel).
create table temp1 (date1 number2(5,10));
insert into temp1(date1) values('40284.3878935185');
select to_date(date1, 'yyyy-mm-dd hh24:mi:ssxff') from temp1
Error report: SQL Error: ORA-01861: literal does not match format
string
01861. 00000 - "literal does not match format string"
*Cause: Literals in the input must be the same length as literals in
the format string (with the exception of leading whitespace). If the
"FX" modifier has been toggled on, the literal must match exactly,
with no extra whitespace.
*Action: Correct the format string to match the literal.
Thanks to Mark Bannister
Now the SQL syntax is:
select to_char(to_date('1899-12-30','yyyy-mm-dd') +
date1,'yyyy-mm-dd hh24:mi:ss') from temp1
but can't fetch the date format like 'yyyy-mm-dd hh24:mi:ss.ff'. Continue look for help.
Using an epoch date of 30 December 1899, try:
select to_date('1899-12-30','yyyy-mm-dd') + date1
Simple date addition doesn't work with timestamps, at least if you need to preserve the fractional seconds. When you do to_timestamp('1899-12-30','yyyy-mm-dd')+ date1 (in a comment on Mark's answer) the TIMESTAMP is implicitly converted to a DATE before the addition, to the overall answer is a DATE, and so doesn't have any fractional seconds; then you use to_char(..., '... .FF') it complains with ORA-01821.
You need to convert the number of days held by your date1 column into an interval. Fortunately Oracle provides a function to do exactly that, NUMTODSINTERVAL:
select to_timestamp('1899-12-30','YYYY-MM-DD')
+ numtodsinterval(date1, 'DAY') from temp3;
16-APR-10 09.18.33.999998400
You can then display that in your desired format, e.g. (using a CTE to provide your date1 value):
with temp3 as ( select 40284.3878935185 as date1 from dual)
select to_char(to_timestamp('1899-12-30','YYYY-MM-DD')
+ numtodsinterval(date1, 'DAY'), 'YYYY-MM-DD HH24:MI:SSXFF') from temp3;
2010-04-16 09:18:33.999998400
Or to restrict to thousandths of a second:
with temp3 as ( select 40284.3878935185 as date1 from dual)
select to_char(to_timestamp('1899-12-30','YYYY-MM-DD')+
+ numtodsinterval(date1, 'DAY'), 'YYYY-MM-DD HH24:MI:SS.FF3') from temp3;
2010-04-16 09:18:33.999
An epoch of 1899-12-30 sounds odd though, and doesn't correspond to Excel as you stated. It seems more likely that your expected result is wrong and it should be 2010-04-18, so I'd check your assumptions. Andrew also makes some good points, and you should be storing your value in the table in a TIMESTAMP column. If you receive data like this though, you still need something along these lines to convert it for storage at some point.
Don't know the epoch date exactly, but try something like:
select to_date('19700101','YYYYMMDD')+ :secs_since_epoch/86400 from dual;
Or, cast to timestamp like:
select cast(to_date('19700101', 'YYYYMMDD') + :secs_since_epoch/86400 as timestamp with local time zone) from dual;
I hope this doesn't come across too harshly, but you've got to totally rethink your approach here.
You're not keeping data types straight at all. Each line of your example misuses a data type.
TEMP1.DATE1 is not a date or a varchar2, but a NUMBER
you insert not the number 40284.3878935185, but the STRING >> '40284.3878935185' <<
your SELECT TO_DATE(...) uses the NUMBER Temp1.Date1 value, but treats it as a VARCHAR2 using the format block
I'm about 95% certain that you think Oracle transfers this data using simple block data copies. "Since each Oracle date is stored as a number anyway, why not just insert that number into the table?" Well, because when you're defining a column as a NUMBER you're telling Oracle "this is not a date." Oracle therefore does not manage it as a date.
Each of these type conversions is calculated by Oracle based on your current session variables. If you were in France, where the '.' is a thousands separator rather than a radix, the INSERT would completely fail.
All of these conversions with strings are modified by the locale in which Oracle thinks your running. Check dictionary view V$NLS_PARAMETERS.
This gets worse with date/time values. Date/time values can go all over the map - mostly because of time zone. What time zone is your database server in? What time zone does it think you're running from? And if that doesn't spin your head quite enough, check out what happens if you change Oracle's default calendar from Gregorian to Thai Buddha.
I strongly suggest you get rid of the numbers ENTIRELY.
To create date or date time values, use strings with completely invariant and unambiguous formats. Then assign, compare and calculate date values exclusively, e.g.:
GOODFMT constant VARCHAR2 = 'YYYY-MM-DD HH24:MI:SS.FFF ZZZ'
Good_Time DATE = TO_DATE ('2012-02-17 08:07:55.000 EST', GOODFMT);

Oracle to_date() incorrect output

There must be a very simple answer, but I can't find it anywhere.
I have the following which is a section of my select statement:
case when q.renewal_date is not null then
to_date(q._renewal_date, 'DD/MM/YYYY')
else
to_date(w.END_DATE, 'DD/MM/YYYY')
end END_DATE,
according to all of the docs I can find the MM should give the month in numbers however I'm getting results such as:
30-SEP-12
26-JUN-11
30-SEP-12
It's also interesting that they're hyphenated (-) and not with slashes (/).
So what's the reason for this and how do I achieve what I want?
Assuming w.end_Date and q._renewal_date are actual dates, you want to to_char them, not to_date. At present I would say you are seeing the dates in the format specified by your NLS settings. (If they are not dates, you are converting them to dates, but still letting your NLS settings choose the format you view it in)
As you are TO_DATEing the value it is stored by Oracle internally as a date. It is displayed back to you using your NLS_DATE settings value which i would assume are set to DD-MON-YY by default.
You can check with
SELECT *
FROM v$parameter
WHERE name = 'nls_date_format';
You'll need to either alter your NLS_DATE_FORMAT setting (either for your session or for the DB) or TO_CHAR the output to the format you want to see.
to_date converts a string to a date. The code you have is taking a string (q._renewal_date) in 'DD/MM/YYYY' format and converting it to a date. What you are seeing is the default rendering of the date field.
Depending on what type q._renewal_date is, you probably need to use a different conversion/formatting function.