oracle date format comparison ORA-01858 - sql

I have this query on production, which had no problem till yesterday:
SELECT E.ID
FROM EXAM_STUD_ENTERANCE E,
EXAM_REGISTRATION R
WHERE E.EXAM_REG_ID = R.ID
AND E.USER_NAME ='user'
AND E.BLOCK = 1
AND E.STATUS = 1
AND TO_DATE (TO_CHAR (SYSDATE, 'DD/MM/YYYY HH24:MI:SS'),
'DD/MM/YYYY HH24:MI:SS') >
TO_DATE (
TO_CHAR (R.EXAM_DATE, 'DD/MM/YYYY')
|| ' ' || R.EXAM_START_TIME
,
'DD/MM/YYYY HH24:MI:SS')
AND TO_DATE (TO_CHAR (SYSDATE, 'DD/MM/YYYY HH24:MI:SS'),
'DD/MM/YYYY HH24:MI:SS') <
TO_DATE (
TO_CHAR (R.EXAM_DATE, 'DD/MM/YYYY')
|| ' ' || R.EXAM_END_TIME
,
'DD/MM/YYYY HH24:MI:SS');
But now I receive an error
ORA-01858: a non-numeric character was found where a numeric was
expected
Type of columns EXAM_START_TIME and EXAM_END_TIME are NVARCHAR2(100), and stores data like '16:40' ; EXAM_DATE is DATE

Yesterday someone inserted a bad value into one of those time columns
Do a
SELECT * FROM EDUMAN_EXAM.EXAM_REGISTRATION
WHERE
NOT(
REGEXP_LIKE(EXAM_START_TIME, '^\d\d:\d\d:\d\d$') AND
REGEXP_LIKE(EXAM_END_TIME, '^\d\d:\d\d:\d\d$')
)
Find the bad data, and remove it
Note: you posted an sql that indicates the time columns store hh:mm:ss and you said "it was working" but then you claimed that the time columns don't store seconds. If they do store seconds, then use the query as above. If they don't store seconds, reduce the regex pattern to \d\d:\d\d
As a side commentary, you should never have made the decision to store this time data as a string. The DATETIME that holds the EXAM_START_DATE can just as easily hold a time, and if you just want the DATE without the time part, you can TRUNC(some_datetime) to remove the time component
Store the data in a column of the proper type, and you won't get this issue, and you wont have to get into this ludicrous date -> string -> concatenate -> parse process on thousands of records

Related

Get date and time from date column in oracle

I inserted date and time in database, now when trying to retrieve date and time both from database only getting time part.
I tried insert date using TO_DATE('08/13/2019 09:10:03', 'MM/DD/YYYY HH24:MI:SS') into 'Time' col. Now trying to get date from table using TO_DATE(Time, 'DD/MON/RR HH24:MI:SS'), but only getting date part. My database nls date format is "DD/MON/RR". 'Time' col is date type and I'm using oracle 10g xe.
I can get date and time using TO_CHAR(Time, 'DD/MON/RR HH24:MI:SS') but as I need to use this in comparison operation like below:
select TO_CHAR(Time,'DD/MON/RR HH24:MI:SS') from Table where (TO_CHAR(Time, 'DD/MON/RR HH24:MI:SS') <= TO_DATE('08/07/2019 10:13:52', 'MM/DD/YYYY HH24:MI:SS'))
it gives this error 'ORA-01830: date format picture ends before converting entire input string'. Also tried to use TO_DATE(TO_CHAR(Time, 'DD/MON/RR HH24:MI:SS')), still it gives only time part. Should I use TIMESTAMP datatype for 'Time' col?
I want to get date and time from table where i can use them in comparison operation.
Date need not be converted into date again.
You can simply write your query like this:
SELECT
TIME -- use to_char for formatting the output date
FROM Table
WHERE
TIME <= TO_DATE('08/07/2019 10:13:52', 'MM/DD/YYYY HH24:MI:SS')
Cheers!!

How to add hours to date in 24 hours format

I would like to add, for example, 8 hours to the enddate in a 24 hour format.
I tried adding + 8/24, 'DD-MM-YYYY HH24:MI:SS' on the first line but this gives an error.
This is my query thus far.
SELECT to_char(IN_ENDDATE, 'DD-MM-YYYY HH24:MI:SS')
INTO IN_END_DATE_STRING
FROM DUAL;
Your first line converts a date to a string. You cannot then add 8/24 to it. Do the addition before the conversion:
SELECT to_char(IN_ENDDATE + 8/24.0, 'DD-MM-YYYY HH24:MI:SS')
INTO IN_END_DATE_STRING
FROM DUAL;
IN_ENDDATE really does need to be a date type to allow +8/24 to work. If it's a timestamp, add it as an interval:
IN_ENDDATE + INTERVAL '8' HOUR
This form might be safer to use for a couple of reasons:
it works on both date and timestamps
it's more readable
If IN_ENDDATE is a non-date type (eg varchar) then your query works without the +8/24 because it is being successfully implicitly converted from varchar to date, before being passed to to_char. In this case either be explicit about your conversion:
SELECT to_char(to_date(IN_ENDDATE, 'YYMMDD WHATEVER') + 8/24.0, 'DD-MM-YYYY HH24:MI:SS')
INTO IN_END_DATE_STRING
FROM DUAL
SELECT to_char(to_date(IN_ENDDATE, 'YYMMDD WHATEVER') + INTERVAL '8' HOUR, 'DD-MM-YYYY HH24:MI:SS')
INTO IN_END_DATE_STRING
FROM DUAL
Or set your IN_ENDDATE parameter to really be a date type

Oracle : Date time subtraction

I have to calculate time difference in minutes from current(sysdate) and modified time:-
to_date(to_char(sysdate, 'YYYY-MM-DD HH24:MI:SS'), 'YYYY-MM-DD HH24:MI:SS')
- to_date(to_char(modified, 'YYYY-MM-DD HH24:MI:SS'), 'YYYY-MM-DD HH24:MI:SS')
but problem is to_char returns proper time:-
to_char(whenmodified, 'YYYY-MM-DD HH24:MI:SS')
Outputs 2016-05-23 14:55:50
and to_date doesn’t show time:-
to_date(to_char(modified, 'YYYY-MM-DD HH24:MI:SS'), 'YYYY-MM-DD HH24:MI:SS')
Outputs: 2016-05-23
Please assist how I can get time difference by converting to_char to to_date.
NOTE:
I cant do sysdate-modified because both sysdate and modified gives date without time e.g 2016-05-23
Using to_char for sysdate or modified give date with time 2016-05-23 14:55:50
As we cant subtracts dates in to_char function I am again converting back them to to_date for getting time.
I am expecting:
2016-05-23 14:55:50 - 2016-05-23 14:53:50 = 2 min
I have to calculate time difference in minutes from current(sysdate) and modified time
Oracle Setup:
CREATE TABLE table_name ( modified DATE );
INSERT INTO table_name
SELECT TIMESTAMP '2016-05-23 14:20:00' FROM DUAL UNION ALL
SELECT TIMESTAMP '2016-05-23 00:00:00' FROM DUAL UNION ALL
SELECT TIMESTAMP '2016-05-01 00:00:00' FROM DUAL UNION ALL
SELECT TIMESTAMP '2016-01-01 00:00:00' FROM DUAL;
Query:
SELECT ( sysdate - modified ) * 24 * 60 AS minute_difference
FROM table_name;
Output:
MINUTE_DIFFERENCE
-----------------
3.66666667
863.666667
32543.6667
206783.667
And to address your comment that:
to_date doesn’t show time
A date always has a time component and never has a format internally to the database (it is represented by 7 or 8 bytes) - the formatting of a date is done by the client program that you use to access the database (and often the default is not to show the time component - however, the time component still exists).
You can change this either in the preferences of your client program or, if they don't use that to control it, by changing the NLS_DATE_FORMAT session parameter:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';

Oracle DB select between dates

I would like to query number of records between night 12.01 AM to 11.59 PM but issue is, I would like to schedule this query so I cant specify any hard coded dates.
Query should pull number of records for query date between 12.01 AM to 11.59 PM.
Could someone please help me on this.
Query should pull number of records for query date between 12.01 AM to 11.59 PM.
You could do it as:
TRUNC gives you date element truncating the time portion
convert the SYSDATE into string using TO_CHAR
then concatenate the time element
finally convert everything back to DATE
SYSDATE returns the current date and time set for the operating system on which the database resides. The datatype of the returned value is DATE, and the format returned depends on the value of the NLS_DATE_FORMAT initialization parameter.
So, you don't have to hard-code any DATE value if you want to execute the query everyday.
Use the following in the filter predicate:
BETWEEN
TO_DATE(TO_CHAR(TRUNC(SYSDATE), 'MM/DD/YYYY') ||' 00:01', 'MM/DD/YYYY HH24:MI')
AND
TO_DATE(TO_CHAR(TRUNC(SYSDATE), 'MM/DD/YYYY') ||' 23:59', 'MM/DD/YYYY HH24:MI')
Demo
SQL> alter session set nls_date_format = 'MM/DD/YYYY HH24:MI:SS';
Session altered.
SQL> SELECT to_date(TO_CHAR(TRUNC(SYSDATE), 'MM/DD/YYYY')
2 ||' 00:01', 'MM/DD/YYYY HH24:MI') start_dt ,
3 to_date(TO_CHAR(TRUNC(SYSDATE), 'MM/DD/YYYY')
4 ||' 23:59', 'MM/DD/YYYY HH24:MI') end_date
5 FROM dual;
START_DT END_DATE
------------------- -------------------
05/06/2015 00:01:00 05/06/2015 23:59:00
SQL>
So, you don't have to put any hard-coded value for current date, the SYSDATE will take care of it. All you are doing is:
TRUNC gives the date element by truncating the time portion.
Then concatenating the required time element
Converting the entire string into DATE using TO_DATE
I would like to schedule this query so I cant specify any hardcord dates
To schedule the query to execute everyday, you could use DBMS_SCHEDULER.
I'm going to assume you want everything that happens during the date of interest. So you want everything from and including midnight of that day and before midnight of the next day.
declare
AsOf Date = date '2015-01-01 13:14:15';
select ...
from tablename
where tabledate >= trunc( AsOf )
and tabledate < trunc( AsOf ) + 1;
If you know the date doesn't have a time portion, just can eliminate the calls to trunc. But you may want to keep them just in case.

Casting String to Date

The below one is working fine and returns date in the desired format
select TO_DATE(TO_CHAR(max(entdate), 'DD/MM/YYYY'), 'DD/MM/YYYY') as last_transaction_date from table;
After adding hh24:mm:ss and error of "format code appears twice" ORA-01810 appears
select TO_DATE(TO_CHAR(max(entdate), 'DD/MM/YYYY hh24:mm:ss'), 'DD/MM/YYYY hh24:mm:ss') as last_transaction_date from table;
I'm not able to understand the difference between both cases
MI not MM for minutes
"Some people mistakenly use the MM format code to represent minutes, thus using the MM format for both the months and the minutes."
select TO_DATE(TO_CHAR(max(entdate), 'DD/MM/YYYY HH24:MI:SS'), 'DD/MM/YYYY HH24:MI:SS') as last_transaction_date from table;