Oracle Date Comparsion - sql

I have a column in TableA which contains date as Varchar2 datatype for column Start_date.( '2011-09-17:09:46:13').
Now what i need to do is , compare the Start_date of TableA with the SYSDATE, and list out any values thts atmost 7days older than SYSDATE.
Can any body help me with this isssue.

You may perform the below to check the date:
select * from
TableA
where
to_date(start_date,'YYYY-MM-DD') between sysdate and sysdate-7;

something like
select * from tableA
where start_date between sysdate-7 and sysdate

I have a column in TableA which contains date as Varchar2 datatype for column Start_date.( '2011-09-17:09:46:13').
Then you have a flawed design. You must use appropriate data types for the data. A datetime should always be stored as DATE data type.
Now what i need to do is , compare the Start_date of TableA with the SYSDATE, and list out any values thts atmost 7days older than SYSDATE.
Since the data type of your column is VARCHAR2, you must use TO_DATE to explicitly convert the string into date.
where to_date(start_date,'YYYY-MM-DD HH24:MI:SS') between sysdate and sysdate-7;
Remember, a DATE has both date and time elements. IF you want to ignore the time portion, then you need to use TRUNC.
For example,
SQL> alter session set nls_date_format='YYYY-MM-DD HH24:MI:SS';
Session altered.
SQL> SELECT sysdate FROM DUAL;
SYSDATE
-------------------
2015-07-28 16:03:32
SQL> SELECT TRUNC(sysdate) FROM DUAL;
TRUNC(SYSDATE)
-------------------
2015-07-28 00:00:00
SQL>
So, BETWEEN sysdate AND sysdate -7 will consider the current datetime till past 7 days till that time portion. If you only want to consider the date portion, use TRUNC.
For example,
where to_date(start_date,'YYYY-MM-DD') between TRUNC(sysdate) and TRUNC(sysdate-7);

Although you ought to be storing your times as DATE data types, you are at least storing the dates in a format that allows greater-than/less-than comparisons.
So, while you ought to convert these columns to dates, or alternatively convert the values to dates for comparison with SYSDATE -7, you could also convert SYSDATE -7 to the same string format as you are storing.
For example:
start_date between to_char(sysdate -7, "YYYY-MM-DD HH24:MI:SS") and
to_char(sysdate , "YYYY-MM-DD HH24:MI:SS")
This would let you use an indexed search without needing a function-based index on the start date column.

Related

SQL: How to data of current date from timestamp field in oracle?

How to data of current date from timestamp field in oracle?
select
jobstatus0_.JOBNAME as JOBNAME1_21_,
jobstatus0_.STARTDATE as STARTDATE2_21_,
jobstatus0_.ENDDATE as ENDDATE3_21_,
jobstatus0_.REMARKS as REMARKS4_21_,
jobstatus0_.STATUS as STATUS5_21_
from
PD_OWNER.CIM_SNOW_JOB_STATUS_TAB jobstatus0_
where
jobstatus0_.JOBNAME='AGREEMENTS'
AND jobstatus0_.STARTDATE=sysdate <-- Not working with this
We need not to consider Time but date only
I tried following but it is also not working.
and cast(jobstatus0_.STARTDATE as date)=sysdate
Also used which worked
AND to_date(to_char(jobstatus0_.STARTDATE,'DD-MON-YYYY'))=to_date(to_char(sysdate,'DD-MON-YYYY'));
but want more elegant way.
You may use the TRUNC(date) function
Purpose
The TRUNC (date) function returns date with the time portion of the day truncated to the unit specified by the format model fmt. The value returned is always of datatype DATE, even if you specify a different datetime datatype for date. If you omit fmt, then date is truncated to the nearest day. Please refer to "ROUND and TRUNC Date Functions" for the permitted format models to use in fmt.
Examples
The following example truncates a date:
SELECT TRUNC(TO_DATE('27-OCT-92','DD-MON-YY'), 'YEAR')
"New Year" FROM DUAL;
New Year
---------
01-JAN-92
If column STARTDATE is DATE (or TIMESTAMP), you could truncate it (as well as SYSDATE) and get
and trunc(jobstatus0_startdate) = trunc(sysdate)
as trunc will remove time component:
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
SQL> select trunc(sysdate) trd,
2 trunc(systimestamp) trt
3 from dual;
TRD TRT
------------------- -------------------
06.02.2020 00:00:00 06.02.2020 00:00:00
SQL>
Though, if there was an index on that column, truncating it will make the index unusable, but that's another story and there is a workaround (function based index or making the column value "between" sysdate at this and next midnight).
In postgresql/ mysql use as below
date(jobstatus0_.STARTDATE)=date(now())
In sql-server
cast(jobstatus0_.STARTDATE as date)=cast(CURRENT_TIMESTAMP as date)

Filtering a dataset by date and time Oracle SQL through Power BI

I'm having trouble with filtering a date and time for anything two hours before and sooner. I tried this:
SELECT *
FROM
table
where
date >= sysdate - 1
AND
TO_DATE( Time, 'HH24:MI:SS' ) >= TO_DATE( sysdate, 'HH24:MI:SS' ) - 2
But I'm getting an inconsistent type error which is what I thought I was handling with the TO_DATE() function but I guess not.
sysdate is already a date (and time), so TO_DATE( sysdate, 'HH24:MI:SS' ) doesn't make any sense.
You didn't provide your data types for your date and time columns in table, so I'm going to assume they're both varchar2(10) with formats MM/DD/YYYY and HH24:MI:SS respectively.
I'm also going to go ahead and change your example table and column names, since they're invalid names to use in a real query.
-- example data
with my_table as (select '06/13/2019' as date_column, '09:40:34' as time_column from dual)
-- your query
SELECT *
FROM
my_table
where
to_date(date_column || ' ' || time_column, 'MM/DD/YYYY HH24:MI:SS') >= sysdate - 2/24
What I'm doing here is to combine your date and time strings into one date-time string, then converting it to an Oracle date type (actually date+time). Then we compare it to sysdate - 2/24, which says to take the current time and subtract 2/24ths of a day, which is 2 hours.
For this example, you might need to change the example data date_column and time_column values to something from the past 2 hours, depending on when you run this and what time zone you're in.

Comparing date stored in date and varchar columns

I have a simple table, in which I have to store date information both in DATE and VARCHAR2 columns:
CREATE TABLE date_test(date_in_varchar VARCHAR2(30), date_in_date DATE);
INSERT INTO date_test values ('06/21/2017 01:30:00 AM', to_date('06/21/2017 01:01:03 AM', 'MM/DD/YYYY HH:MI:SS AM'));
INSERT INTO date_test values ('06/22/2017 02:45:00 AM', to_date('06/22/2017 05:06:01 AM', 'MM/DD/YYYY HH:MI:SS AM'));
INSERT INTO date_test values ('06/23/2017 05:51:20 AM', to_date('06/23/2017 12:00:05 AM', 'MM/DD/YYYY HH:MI:SS AM'));
As you can see, format of data is 'MM/DD/YYYY HH:MI:SS AM'. I have to prepare comparisons between date passed in variable l_attr_val format 'MM/DD/YYYY' and ones stored in the table. Now my question is: What is the best and safest way, to write queries for filters: equals, like, greater, lower, to be sure, that I won't face implicit conversion? I assume, that query would be different for values stored as date and for values stored as varchar.
CASE 1: Date is stored in DATE column and it has information about day, month, year, hour, minutes, seconds. I also have a variable (of VARCHAR2 type), that has information of only day, month, year. (l_attr_val = '06/21/2017'). Now I want to make an equality filter between this variable and values stored in table, based only on date, without time (I get 21st of June 2017 in variable and I want to see all records from 21st of June 2017, no matter the time).
SELECT * FROM date_test WHERE date_in_date = TO_DATE('06/22/2017', 'MM/DD/YYYY');
It gives me 0 rows because of the times.
CASE 2, separate from CASE 1:
CASE 1: Date is stored in VARCHAR2 column and it has information about day, month, year, hour, minutes, seconds. I also have a variable (of VARCHAR2 type), that has information of only day, month, year. (l_attr_val = '06/21/2017'). Now I want to make an equality filter between this variable and values stored in table, based only on date, without time (I get 21st of June 2017 in variable and I want to see all records from 21st of June 2017, no matter the time).
SELECT * FROM date_test WHERE TO_DATE(date_in_varchar, 'MM/DD/YYYY HH:MI:SS AM' = TO_DATE('06/22/2017', 'MM/DD/YYYY');
So, what is the safest way to compare dates in above mentioned cases?
Case 1: Properly stored dates (date type)
You could convert your date_in_date column to drop time part but this would not take advantage of non-functional index on this colum so I would advise not to go that way. Instead, if 06/22/2017 is your VARCHAR2 type variable you could also modify it on the fly to have one more value which is incremented by 1 day. This would make use of plain index on date_in_date function and the query would look like:
SELECT * FROM date_test
WHERE date_in_date >= TO_DATE('06/22/2017', 'MM/DD/YYYY')
AND date_in_date < TO_DATE('06/23/2017', 'MM/DD/YYYY')
You could also add +1 after the second part and use the same variable to save you the time for doing math by yourself on a variable.
Case 2: Dates stored as varchars
You need to convert your date_in_varchar to date without time part (or with it, and then partially apply logic proposed for case 1) and also convert your input variable the same way. If you decide to convert it to date without time part then below query would take advantage of functional index (but not a plain one):
SELECT * FROM date_test
WHERE TO_DATE(SUBSTR(date_in_varchar, 0, 12), 'MM/DD/YYYY') = TO_DATE('06/22/2017', 'MM/DD/YYYY')
Should you decide on converting it to a date with time part query would be similar to case 1, but with proper formating. I would advise you to create a functional index on this conversion to date with trimming the varchar to characters containing only date if your queries are going to be accurate up to one day.
If there are indexes on these columns I would use:
Case 1:
select * from date_test
where date_in_date >= to_date('06/22/2017', 'MM/DD/YYYY')
and date_in_date < to_date('06/22/2017', 'MM/DD/YYYY') + 1;
Case 2:
select * from date_test where date_in_varchar like '06/22/2017%'
After some more research I used below approach:
Case 1: Properly stored dates (date type)
SELECT * FROM date_test
WHERE TRUNC(date_in_date)= to_date('06/22/2017', 'MM/DD/YYYY', 'nls_date_language = ENGLISH');
Case 2: Dates stored as varchars
SELECT * FROM date_test
WHERE TRUNC(TO_DATE(date_in_varchar, 'MM/DD/YYYY HH:MI:SS AM')) = to_date('06/22/2017', 'MM/DD/YYYY', 'nls_date_language = ENGLISH');

What is Oracle's Default Date Format?

I have an Oracle DB, and I don't control the date format. I want to know what the date format is to ensure that searches like
select * from search where search_date>='03/16/2016 00:00:00'
work as expected.
Don't do that - you are relying on implicit data type conversion which is going to fail at some point.
You have two options:
1) Use a proper ANSI SQL date literal:
select *
from search
where search_date >= timestamp '2016-03-16 00:00:00';
2) use to_date() (or to_timestamp()) and use a custom format.
select *
from search
where search_date >= to_date('03/16/2016 00:00:00', 'mm/dd/yyyy hh24:mi:ss');
With to_date() you should avoid any format that is language dependent. Use numbers for the month, not abbreviations (e.g. 'Mar' or 'Apr') because they again rely on the client language.
More details can be found in the manual: https://docs.oracle.com/cd/E11882_01/server.112/e41084/sql_elements003.htm#SQLRF51062
Never rely on implicit data type conversion.
You can get all the NLS session parameters with the query:
SELECT * FROM NLS_SESSION_PARAMETERS;
or, if you have the permissions GRANT SELECT ON V_$PARAMETER TO YOUR_USERNAME;, you can use the command:
SHOW PARAMETER NLS;
If you just want the date format then you can do either:
SELECT * FROM NLS_SESSION_PARAMETERS WHERE PARAMETER = 'NLS_DATE_FORMAT';
or
SHOW PARAMETER NLS_DATE_FORMAT;
However, you could also use ANSI date (or timestamp) literals which are format agnostic. An ANSI date literal has the format DATE 'YYYY-MM-DD' and a timestamp literal has the format TIMESTAMP 'YYYY-MM-DD HH24:MI:SS.FF9'. So your query would be:
select * from search where search_date>= DATE '2016-03-16'
or
select * from search where search_date>= TIMESTAMP '2016-03-16 00:00:00'
What is Oracle's Default Date Format?
A DATE doesn't have any format. Oracle does not store dates in the format you see. It stores it internally in 7 bytes with each byte storing different components of the datetime value.
Byte Description
---- -------------------------------------------------
1 Century value but before storing it add 100 to it
2 Year and 100 is added to it before storing
3 Month
4 Day of the month
5 Hours but add 1 before storing it
6 Minutes but add 1 before storing it
7 Seconds but add 1 before storing it
To display, use TO_CHAR with proper FORMAT MODEL.
For comparing, use TO_DATE with proper FORMAT MODEL.
What you see as a format by default, is your locale specific NLS settings.
SQL> select parameter, value from v$nls_parameters where parameter='NLS_DATE_FORMAT';
PARAMETER VALUE
--------------- ----------------------------------------------------------------
NLS_DATE_FORMAT DD-MON-RR
SQL> select sysdate from dual;
SYSDATE
---------
17-MAR-16
SQL> select to_char(sysdate, 'mm/dd/yyyy hh24:mi:ss') from dual;
TO_CHAR(SYSDATE,'MM
-------------------
03/17/2016 12:48:41
SQL>
search_date>='03/16/2016 00:00:00'
You are comparing a DATE with a string literal. Always, explicitly convert the string into date using TO_DATE and proper format mask.
TO_DATE('03/16/2016', 'MM/DD/YYYY')
Or, if you dealing only with the date part and not concerned with the time portion, then use the ANSI date literal which uses a fixed format DATE 'YYYY-MM-DD'
DATE '2016-03-16'
You might just be lucky to get an output due to an implicit datatype conversion based on your locale specific NLS settings. Never ever rely on implicit datatype conversion, it might work for you, might fail for others where the nls settings are different.

store dates in oracle

I have a table as
create table Dummy (date_created date)
in oracle.I want to store date in 'dd-mon-yyyy' (12-dec-2010) format.
How should i do this.
Please help.
In Oracle a column created with the DATE datatype just stores the date. It doesn't have a particular format, it just stores the day, month, year, hour, minute, and second. You need to convert from whatever format you have using the TO_DATE function. If you have a text string with the date in 'dd-mon-yyyy' format and you want to put this date into your table you'd use something like
INSERT INTO DUMMY (DATE_CREATED)
VALUES (TO_DATE('01-FEB-2011', 'DD-MON-YYYY');
Going the other way (from DATE column value to character string) you'd use the TO_CHAR function. If you were retrieving a value from your table and wanted to convert it to 'DD-MON-YYYY' format you'd use something like
SELECT TO_CHAR(DATE_CREATED, 'DD-MON-YYYY')
FROM DUMMY;
Share and enjoy.
Use to_date() function. In your case, the syntax would be
insert into Dummy values (to_date('08-09-2010', 'dd-mm-yyyy'));
Here is a link to the detailed help.
The DATE datatype will store date and time information (century, year, month, day, hours, minutes, and seconds) in an internal format in the database. When you get it out of the database, you can choose to display it in whatever format you like.
This information is either created using implicit conversion from a string or explicitly using either the TO_DATE function or the ANSI date literal. If you look in the v$nls_parameters view, this will tell you what the NLS_DATE_FORMAT is which is generally used for the implicit conversion. This may often be defined as DD-MON-RR, which might be why the date will come out as 23-DEC-10 when the query select sysdate from dual is run. (Not entirely sure I'm right about the nls stuff. Correct me if I'm wrong.)
However, all the date information is available if you know how to get it. The query select to_char(sysdate, 'dd-mon-yyyy hh24:mi:ss') from dual will return all the date fields.
Likewise, the insert statement shown below will create a row with a date value in it.
insert into dummy (date_created)
values (to_date('12-dec-2010 12:34:56', 'dd-mon-yyyy hh24:mi:ss'))`
This data can then be retrieved.
select date_created from dummy
This will implicitly convert the date to a character string using the NLS_DATE_FORMAT, providing the output below.
DATE_CREA
---------
23-DEC-10
The full date information is available by explicitly converting the date to a character string.
select to_char(date_created, 'DD-MON-YYYY') as date_created from dummy;
select to_char(date_created, 'DD-MON-YYYY HH24:MI:SS') as date_created
from dummy;
This will provide output in the format you require:
DATE_CREATE
-----------
23-DEC-2010
If you always use the TO_DATE and TO_CHAR functions to convert to/from a date datatype, then you will have fewer problems. Implicit conversion is useful but can cause some confusion or problems.
You can keep and eye here
http://www.techonthenet.com/oracle/functions/to_date.php
use to_date function to save a data with the format you need. I suggest to use SYSDATE updating table and when you need to read data from table use something like that:
dbms_output.put_line(TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS'));
to solve your problem use:
to_date('08/JAN/2010', 'DD/MON/YYYY')
Just use TRUNC(YourDate) if date have time part, it will be truncate time part. Oracle have not just 'DATE' type, 'DATE' always have time part.
However if you do not specify time - it will 00:00:00.
SELECT TRUNC(SYSDATE) from dual
Result:
23-12-2010
Oracle does not support DATE without time part.
You can make it always be an integer date by adding a CHECK constraint:
CREATE TABLE dummy (date_created date CHECK (date_created = TRUNC(date_created)))
, insert it in any format you want:
INSERT
INTO dummy (date_created)
VALUES (TO_DATE('23-DEC-2010', 'dd-mon-yyyy'))
and select it in any format you want:
SELECT TO_CHAR(date_created, 'dd-mon-yyyy')
FROM dummy