I'm new to Oracle 11g & I have a question about a query.
I have a table dummy which has created_date column of type Date.
I want a query which will return all the records where created_date + 7 days is less than today's date.
What type of query in Oracle 11g accomplishes this?
Oracle lets you use + for date arithmetic, so
where table.created_date >= sysdate
and table.created_date < sysdate + 7
will find rows between exactly now and exactly now plus 7 days.
If you don't want to include the time component, you can use the trunc() function
where trunc(table.created_date) >= trunc(sysdate)
and trunc(table.created_date) < trunc(sysdate) + 7
I think rejj's solution will give you the records between now and seven days in the future. From your description, it sounds like you probably want those records within the past seven days. I'd do this as:
WHERE created_date <= SYSDATE
AND created_date >= SYSDATE - 7
This may be more clear, and is equivalent:
WHERE created_date BETWEEN SYSDATE AND (SYSDATE - 7)
Be aware that using TRUNC() will cause the optimizer to bypass any indexes you have on created_date, unless you have a functional index defined.
Using INTERVAL constants can make date arithmetic clearer, as in
SELECT *
FROM DUMMY
WHERE CREATED_DATE >= TRUNC(SYSDATE) - INTERVAL '7' DAY
Share and enjoy.
Related
In Oracle SQL Developer, I have a table called t1 who have two columns col1 defined as NUMBER(19,0) and col2 defined as TIMESTAMP(3).
I have these rows
col1 col2
1 03/01/22 12:00:00,000000000
2 03/01/22 13:00:00,000000000
3 26/11/21 10:27:11,750000000
4 26/11/21 10:27:59,606000000
5 16/12/21 11:47:04,105000000
6 16/12/21 12:29:27,101000000
My sysdate looks like this:
select sysdate from dual;
SYSDATE
03/03/22
I want to create a stored procedure (SP) which will delete rows older than 2 months and displayed message n rows are deleted
But when i execute this statement
select * from t1 where to_date(TRUNC(col2), 'DD/MM/YY') < add_months(sysdate, -2);
I don't get the first 2 rows of my t1 table. I get more than 2 rows
1 03/01/22 12:00:00,000000000
2 03/01/22 13:00:00,000000000
How can i get these rows and deleted it please ?
In Oracle, a DATE data type is a binary data type consisting of 7 bytes (century, year-of-century, month, day, hour, minute and second). It ALWAYS has all of those components and it is NEVER stored with a particular formatting (such as DD/MM/RR).
Your client application (i.e. SQL Developer) may choose to DISPLAY the binary DATE value in a human readable manner by formatting it as DD/MM/RR but that is a function of the client application you are using and not the database.
When you show the entire value:
SELECT TO_CHAR(ADD_MONTHS(sysdate, -2), 'YYYY-MM-DD HH24:MI:SS') AS dt FROM DUAL;
Then it outputs (depending on time zone):
DT
2022-01-03 10:11:28
If you compare that to your values then you can see that 2022-01-03 12:00:00 is not "more than 2 months ago" so it will not be matched.
What you appear to want is not "more than 2 months ago" but "equal to or more than 2 months, ignoring the time component, ago"; which you can get using:
SELECT *
FROM t1
WHERE col2 < add_months(TRUNC(sysdate), -2) + INTERVAL '1' DAY;
or
SELECT *
FROM t1
WHERE TRUNC(col2) <= add_months(TRUNC(sysdate), -2);
(Note: the first query would use an index on col2 but the second query would not; it would require a function-based index on TRUNC(col2) instead.)
Also, don't use TO_DATE on a column that is already a DATE or TIMESTAMP data type. TO_DATE takes a string as the first argument and not a DATE or TIMESTAMP so Oracle will perform an implicit conversion using TO_CHAR and if the format models do not match then you will introduce errors (and since any user can set their own date format in their session parameters at any time then you may get errors for one user that are not present for other users and is very hard to debug).
db<>fiddle here
Perhaps just:
select *
from t1
where col2 < add_months(sysdate, -2);
i have a problem with a date parameter query using 'between' operator in oracle view, when i do this query :
SELECT *
FROM MY_VIEW
WHERE STATUS = 'Active'
AND CHECKER_DATE BETWEEN to_date(sysdate - 1, 'DD-MON-YY') AND to_date(sysdate, 'DD-MON-YY');
it does not give me the records (actualy i have any record on that date).
I try using 'in' operator, but still not give me the records.
Please throw some information for this.
*checker_date defined as date
Your first error is to call to_date() on a value that is already a DATE. to_date() expects a VARCHAR value, so sysdate will be first converted to VARCHAR and will then immediately be converted back to a DATE value which it was to begin with.
You probably want
AND CHECKER_DATE BETWEEN trunc(sysdate) - 1 AND trunc(sysdate)
Most probably this will still not give you want you want as that would not include rows from "today". trunc(sysdate) means "today at midnight" and any row that was created today after midnight will not be included. With date/time values (and Oracle's DATE type does contain a time, despite the name) it's better to not use BETWEEN, but explicit range operators instead:
AND CHECKER_DATE >= trunc(sysdate) - 1
AND CHECKER_DATE < trunc(sysdate) + 1
trunc(sysdate) + 1 is tomorrow at midnight, so any value that is (strictly) smaller than that is "today".
All the above assumes that CHECKER_DATE is defined as DATE or TIMESTAMP
You can try:
SELECT *
FROM MY_VIEW
WHERE STATUS = 'Active'
AND CHECKER_DATE BETWEEN trunc(sysdate - 1) AND trunc(sysdate);
Oracle advises against using to_date for date. Also trunc is here because Trunc removes the time component.
may be records are not 'Active' or 'Active' a not-existing value in one of the reference tables if any and trunc(sysdate -1) and trunc(sysdate) would help
This question already has answers here:
How to store only time; not date and time?
(5 answers)
Closed 8 years ago.
I would like to insert data to db as time, not date. If I use to_date('2012-08-31 07:39:33', 'YYYY-MM-DD HH24:MI:SS') it adds date too.
If I use to_date('09:34:00', 'HH24:MI:SS') it adds year, month, day as well, from nowhere :|
Later I need to get rows where time is between x and y, not taking in account the year, month or day. How do I do that?
thanks
As an alternative to the date solution Dave shows, you could use an interval data type for the column:
create table t42(id number, t interval day to second);
insert into t42 (id, t) values(123, to_dsinterval('0 07:39:33'));
insert into t42 (id, t) values(456, to_dsinterval('0 09:34:00'));
select id
from t42
where t between to_dsinterval('0 07:00:00') and to_dsinterval('0 07:59:59');
ID
----------
123
Displaying intervals is a little awkward as they don't have format models, but see this question for some ideas if needed. If you only use them for filtering then that may not be an issue at all.
A DATE type always includes the date component.
One option is to continue using DATE and write your code to ignore the date component. In order to make queries on the time efficient, you might want to create a function-based index on something like TO_CHAR( date_field, 'HH24:MI:SS' ) and use that expression in your queries.
Alternatively, you could use a NUMBER field to store the number of seconds since midnight, and write your queries in terms of that.
you can use number column type and insert value as
INSERT INTO table_name (nTime)
VALUES (date - trunc(date));
and then select values
select *
from table_name t
where t.nTime between (10 / 24 + 15 / 24 / 60) and (12 / 24 + 30 / 24 / 60) --between 10:15 and 12:30
We are using Oracle database.
In our table timestamp is stored as seconds since 1970, how can I convert the time stamp obtained through current_timestamp() function to seconds
This would do it:
select round((cast(current_timestamp as date) - date '1970-01-01')*24*60*60) from dual
Though I wouldn't use current_timestamp if I was only interested in seconds, I would use SYSDATE:
select round((SYSDATE - date '1970-01-01')*24*60*60) from dual
Maybe not completely relevant. I had to resolve other way around problem (e.g. Oracle stores timestamp in V$RMAN_STATUS and V$RMAN_OUTPUT) and I had to convert that to date/timestamp. I was surprised, but the magic date is not 1970-01-01 there, but 1987-07-07. I looked at Oracle's history and the closest date I can think of is when they ported Oracle products to UNIX. Is this right?
Here's my SQL
SELECT /*+ rule */
to_char(min(stamp)/(24*60*60) + date '1987-07-07', 'DD-MON-YYYY HH24:MI:SS') start_tm
, to_char(to_char(max(stamp)/(24*60*60) + date '1987-07-07', 'DD-MON HH24:MI:SS')) end_tm
FROM V$RMAN_STATUS
START WITH (RECID, STAMP) =
(SELECT MAX(session_recid),MAX(session_stamp) FROM V$RMAN_OUTPUT)
CONNECT BY PRIOR RECID = parent_recid ;
I needed to send timestamp to GrayLog via GELF from Oracle DB. I tried different versions and solutions but only one worked correctly.
SQL:
SELECT REPLACE((CAST(dat AS DATE) - TO_DATE('19700101', 'YYYYMMDD')) * 86400 + MOD(EXTRACT(SECOND FROM dat), 1), ',', '.') AS millis
FROM (SELECT SYSTIMESTAMP AT TIME ZONE 'GMT' AS dat FROM dual)
The result for Systmiestamp
2018/12/18 19:47:29,080988 +02:00
will be
1545155249.080988
(Oracle) I have to return all records from last 12 months. How to do that in PL/SQL?
EDIT: Sorry, I forgot to explain, I do have a column of DATA type
Doing this in PL/SQL is pretty much synonymous with doing it in SQL.
SELECT *
FROM table
WHERE date_column >= ADD_MONTHS(TRUNC(SYSDATE),-12)
You might like to fiddle around with the TRUNC statement to get exactly the range you want -- I used TRUNC(SYSDATE) which is the same as TRUNC(SYSDATE,'D') -- ie. remove the time portion of the sysdate. For example, if it is currently Aug 12 but you want values from Feb 01 instead of Feb 12 then use:
SELECT *
FROM table
WHERE date_column >= ADD_MONTHS(TRUNC(SYSDATE,'MM'),-12)
Also, see the docs for treatment of months having different numbers of days: http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/functions004.htm#SQLRF00603
SELECT *
FROM table
WHERE date_column > ADD_MONTHS(SYSDATE, -12)
Not sure I deserved down-modding for the earlier posts... was only trying to help.
SELECT *
FROM table
WHERE date_column > SYSDATE - 365