In Oracle Database, TO_CHAR(Date) gives the result '00-000-00' - sql

I have a date column which I need to convert to character. But doing so it retrieves '00-000-00' even though the actual data has date value. Also, when I convert it again to date it gives the next day value.
For example:
Value: 25-MAR-17 (Date Datatype)
TO_CHAR(Value, 'DD-MON-YY'): '00-000-00'
TO_DATE(Value, 'DD-MON-YY'): '26-MAR-17'
And it's not happening for all the values but only the recent values.
Here is the Dump value present in that date column:
select OrderNumber, LoanDate, Dump(LoanDate) from OrderDetail
where OrderNumber=283402
OrderNumber| LoanDate | Dump(LoanDate)
283402 | 26-MAR-17 | Typ=12 Len=7: 120,117,3,27,0,15,40
Can you please explain me why these weird things happening and how to handle this?

Putting as answer instead of comment, as it would be too big for comment
What you are saying about 0 is not possible. You might get zeroes, if you have set NLS_DATE_FORMAT to display only time. Also you might get next date due to timezone conversion.
To troubleshoot it follow these steps, edit the question, and give the output in the question.
SELECT * FROM nls_session_parameters;
Run select sysdate from dual; and show the output.
Run this alter session set nls_date_format = 'DD-MON-YYYY HH24:MI:SS';
Run select sysdate from dual and show the output.
Now select your date again, select <date column> from <your table> where rownum<2;
Run select to_char(date_column,'DD-MON-YYYY') from your_table where row_num<2;

Related

Date difference = 0 in where clause Oracle?

I have the same problem as this. The only difference is that I use Oracle. I want to select the rows which has insertion_date='20.11.2018'. So my query was
select * from table where insertion_date='20.11.2018'
In that question they suggested datediff, so I looked at its equivalent in oracle and I learned that I can do date arithmetic. So I tried somethings like these:
select * from table where insertion_date -'20.11.2018'=0;
It gave ora-00932 inconsistent datatypes expected date got number.
So, then I tried;
select * from table where insertion_date - to_date('20.11.2018', 'dd.MM.YYYY') = 0;
It does not give error but also does not display the results which I know there must be. What am I doing wrong here? Thanks.
Update: Sorry I forgot to mention that insertion_date is type date. But it also has time(hour, minutes, seconds) info in it.
What is INSERTION_DATE's datatype?
If it is DATE, then comparing it to another date (note: this is date literal; value you used is a string!)
select * from table where insertion_date = date '2018-11-20'
might work, unless INSERTION_DATE contains time component (hours and minutes). Then, the simplest option is to truncate its value (so that you get date itself, at midnight):
select * from table where trunc(insertion_date) = date '2018-11-20'
but it'll ruin index you have on that column (unless it is a function-based one). For small tables, it won't make any difference. For large amount of data, it would so convert it to
select * from table where insertion_date >= date '2018-11-20'
and insertion_date < date '2018-11-21'
If, on the other hand, INSERTION_DATE is a string (VARCHAR2 or CHAR) datatype (which is a really bad idea; consider switching to DATE datatype), then you have to know its format, convert it to DATE first and then compare to another date. For example, if it was a string that contains date values in format dd.mm.yyyy, then
select * from table where to_date(insertion_date, 'dd.mm.yyyy') = date '2018-11-20'
This will certainly fail if any string in that column doesn't match such a format or contains invalid values (such as "date" 53.67.Bx48).

Issue querying date from oracle.

I understand that querying a date will fail as its comparing a string to date and that can cause an issue.
Oracle 11.2 G
Unicode DB
NLS_DATE_FORMAT DD-MON-RR
select * from table where Q_date='16-Mar-09';
It can be solved by
select * from table where trunc(Q_date) = TO_DATE('16-MAR-09', 'DD-MON-YY');
What I don't get is why this works.
select* from table where Q_date='07-JAN-08';
If anyone can please elaborate or correct my mindset.
Thanks
Oracle does allow date literals, but they depend on the installation (particularly the value of NLS_DATE_FORMAT as explained here). Hence, there is not a universal format for interpreting a single string as a date (unless you use the DATE keyword).
The default format is DD-MM-YY, which seems to be the format for your server. So, your statement:
where Q_date = '07-JAN-08'
is interpreted using this format.
I prefer to use the DATE keyword with the ISO standard YYYY-MM-DD format:
where Q_Date = DATE '2008-01-07'
If this gets no rows returned:
select * from table where Q_date='16-Mar-09';
but this does see data:
select * from table where trunc(Q_date) = TO_DATE('16-MAR-09', 'DD-MON-YY');
then you have rows which have a time other than midnight. At this point in the century DD-MON-RR and DD-MON-YY are equivalent, and both will see 09 as 2009, so the date part is right. But the first will only find rows where the time is midnight, while the second is stripping the time off via the trunc, meaning the dates on both sides are at midnight, and therefore equal.
And since this also finds data:
select* from table where Q_date='07-JAN-08';
... then you have rows at midnight on that date. You might also have rows with other times, so checking the count with the trunc version might be useful.
You can check the times you actually have with:
select to_char(q_date, 'YYYY-MM-DD HH24:MI:SS') from table;
If you do want to make sure you catch all times within the day you can use a range:
select * from table where
q_date >= date '2009-03-16'
and q_date < date '2009-03-17';
Quick SQL Fiddle demo.
Although it sounds like you're expecting all the times to be midnight, which might indicate a data problem.

how to delete the records which is inserted 1 day ago

I dont have proper timestamp in table; is it possible to delete 1 day old logs even now?
I have a column name as SESSION_IN which is basically a VARCHAR datatype, and the value will be like
2013-10-15 02:10:27.883;1591537355
is there any way to trim the number after ; and is it possible to compare with "sysdate" identifier?
This SP should compare all the session IDs with current datetime and it should delete if it is older then 1 day.
You can igonre time part and convert date into required format somthing like this
SYSDATE - to_date('date_col','YYYY-DD-MM')
then you can perform operations.
Use the Substring function to extract the datetime portion from the record, then use convert to datetime to cast it to datetime, and then finally use datediff to check if it was inserted yesterday. Use all these caluses in a
DELETE FROM table
WHERE ___ query
For Oracle you could use something like this:
SELECT
TRUNC(to_timestamp(SUBSTR('2013-10-15 02:10:27.883;1591537355',1,
(
SELECT
instr('2013-10-15 02:10:27.883;1591537355', ';')-1
FROM
dual
)
), 'YYYY-MM-DD HH:MI:SS.FF'))
FROM
dual;
Which gives you just the date portion of your input string. Just subtract the amount of days you want to log at the end.
Hope following query helps you:
Select Convert(Datetime,Substring('2013-10-15 02:10:27.883;1591537355',1,23)), DateDiff(dd,Convert(Datetime,Substring('2013-10-15 02:10:27.883;1591537355',1,23)),Getdate())

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

Issue with Fetching Date using SYSDATE?

I have a table structure having a EMP_DATE column as below
ID EMP_DATE
---- -----------
5400 14-FEB-2012
and i have inserted records into the table as below
INSERT INTO TEST_DATE VALUES(5400,SYSDATE);
After inserting records while i am trying to fetch the records of those who has EMP_DATE
as SYSDATE its giving no rows selected.
For time being let the SYSDATE be '01-JUL-2012`
SELECT * FROM TEST_DATE WHERE EMP_DATE = SYSDATE;
(OR)
SELECT * FROM TESt_DATE WHERE EMP_DATE = '01-JUL-2012';
i was not able figure out any solution .
Any suggestions would be helpful .
The main problem is that a date includes hours, minutes and seconds, which you're not allowing for. If you want everything for a single day you can use the trunc function in order to get this:
SELECT * FROM TEST_DATE WHERE trunc(EMP_DATE) = trunc(SYSDATE);
By default trunc removes the time portion of a date, when operating on a date column. I would normally recommend a functional index on trunc(emp_date) in order to optimize this query. Something like:
create index i_test_date on test_date(trunc(emp_date));
I've built a little SQL Fiddle to demonstrate this.
There is an additional problem; though Oracle does support ANSI date literals your second query is wrong. Always, explicitly convert to a string to a date using the to_date function.
SELECT * FROM TEST_DATE WHERE EMP_DATE = to_date('01-07-2012','dd-mm-yyyy');
I've used the mm datetime format model instead of mon as there's no guarantee that JUL will always mean July; it depends on your NLS parameters, what "date language" your particular database or session is using. A datetime format model is how you tell the database the format of whatever string you're passing it to be converted into a date.
If you're interested the ANSI syntax for your second query would be:
SELECT * FROM TESt_DATE WHERE trunc(EMP_DATE) = DATE '2012-07-01'
It must be in this format (YYYY-MM-DD) to work.