This question already has answers here:
adding months to a date SQL
(3 answers)
Closed 11 months ago.
I need to be able to update a specific column in a table that is a time stamp. Its an expirationdate column and I need to add 5 years to the values in that. For these specific ids that are set to expire at some future date.Could anyone provide an example?
I presume that expiration date doesn't actually contain fractional seconds; that's most probably truncated to day, so date datatype is date. If that's so, then add_months is one option: 5 (years) * 12 (months) = 60 monts:
SQL> create table test as
2 select sysdate as expiration_date from dual;
Table created.
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
SQL> select expiration_date,
2 add_months(expiration_date, 12 * 5) new_value
3 from test;
EXPIRATION_DATE NEW_VALUE
------------------- -------------------
06.04.2022 21:28:13 06.04.2027 21:28:13
SQL>
In order to update current values, you'd
update test set
expiration_date = add_months(expiration_date, 12 * 5)
where ...
Related
In my table I have 3 dates that are important:
Scrap_Date
Due_Date
Follow_Up_Date
The Scrap Date is entered into a form. I would like to have the form to where once the "Scrap_Date" is entered, "Due_Date" would automatically populate a date 7 days later, and "Follow_Up_Date" would automatically populate t a date 14 days later.
I still want these dates to display on the form, but for them to automatically populate to these dates without being able to be changed.
What is the best way to go about this?
I've tried setting up a Select List, but struggled with what to code with SQL.
I have also tried this to no success:
select SCRAP_DATE,
DUE_DATE,
FOLLOW_UP_DATE,
from SCRAP_BODY_SYSTEM
where DUE_DATE = SCRAP_DATE + 7
AND FOLLOW_UP_DATE = SCRAP_DATE + 14
I appreciate any help, thank you!
Not sure about APEX GUI issues but two points:
you seem to select rows which already satisfy your "T, T+7, T+14" condition. You might rather want to somehow derive them, for instance compute in select clause?
the syntax for date addition is
select SCRAP_DATE, SCRAP_DATE + interval '7' day, SCRAP_DATE + interval '14' day
from SCRAP_BODY_SYSTEM
You shouldn't be doing it that way. If due_date and follow_up_date are always 7/14 days after scrap_date, then what's their purpose? You can always calculate them when you need them.
If you still want to have them in the table, make them virtual (see lines #5 and 6); doing so, Oracle will do everything for you.
SQL> create table test
2 (id number generated always as identity,
3 scrap_date date,
4 --
5 due_date date as (scrap_date + 7),
6 follow_up_date date as (scrap_date + 14),
7 --
8 constraint pk_test primary key (id)
9 );
Table created.
(just to know what is what; you don't have to do this):
SQL> alter session set nls_date_format = 'dd.mm.yyyy';
Session altered.
In your Apex form, you'd insert only scrap_date:
SQL> insert into test (scrap_date) values (date '2022-06-15');
1 row created.
Table contents is then:
SQL> select * from test;
ID SCRAP_DATE DUE_DATE FOLLOW_UP_
---------- ---------- ---------- ----------
1 15.06.2022 22.06.2022 29.06.2022
SQL>
See? Everything is already set.
I have a datetime column.
I want two columns: a date and a time column.
How can I split my column into two?
Use:
a DATE data-type with the time component set to midnight for the date (you can enforce this with a check constraint); and
an INTERVAL DAY(0) TO SECOND data-type for the time component.
CREATE TABLE table_name(
datetime_column DATE,
date_column DATE,
time_column INTERVAL DAY(0) TO SECOND,
CONSTRAINT table_name__date_column__chk CHECK (date_column = TRUNC(date_column))
)
If you want to get the combined date-time then you can easily add the two to get back to a date-time value.
How can I split my column into two?
Assuming you have the columns you can use:
UPDATE table_name
SET date_column = TRUNC(datetime_column),
time_column = (datetime_column - TRUNC(datetime_column)) DAY TO SECOND;
db<>fiddle here
As Gordon commented, there's no time datatype in Oracle.
Though, literally answering what you asked, you can separate date and time and store each of them into their own columns - it's just that these will be VARCHAR2 columns and you can only look at how pretty they are. You can't, for example, do any date arithmetic on them; first you'd have to convert them back to date datatype, so question is what you really want to do with what you get.
Anyway, here you are:
SQL> create table test
2 (datum date,
3 date_only varchar2(10),
4 time_only varchar2(8)
5 );
Table created.
Sample value:
SQL> insert into test (datum) values (sysdate);
1 row created.
Split date to two parts:
SQL> update test set
2 date_only = to_char(datum, 'dd.mm.yyyy'),
3 time_only = to_char(datum, 'hh24:mi:ss');
1 row updated.
What's in there?
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
SQL> select * from test;
DATUM DATE_ONLY TIME_ONL
------------------- ---------- --------
05.08.2021 21:05:06 05.08.2021 21:05:06
SQL>
Since there is no specific datatype for time, here my suggestion would be to keep the datetime in main column and add two VIRTUAL COLUMN for date value and time value respectively.
Oracle 11g has introduced a new feature that allows you to create a VIRTUAL COLUMN, an empty column that contains a function upon other table columns (the function itself is stored in the data dictionary).
However, it all depends on what you are going to do with it.
Please elaborate your requirement so that you will get a more specific answer.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
Please help me to convert input "21-03-18 14:01:03.000000000 AMERICA/TORONTO" which is in TIMESTAMP(6) WITH TIME ZONE datatype to output "2021-03-18 14:01:03.000-04:00" in Oracle.
As stated so, so, so many times before, if your "input' is a column or variable of type TIMESTAMP (any variant of that) then the data is NOT "21-03-18 14:01:03.000000000 AMERICA/TORONTO". Oracle DATE and TIMESTAMP types are internal, binary structures. The "format" is a string representation for humans to read.
As your question reads, the answer is simply to use the TO_CHAR function to convert that internal TIMESTAMP to whatever format you wish to see:
select to_char(my_timestamp_column,'yyyy-mm-dd hh24:mi:ss') from my_table;
See the SQL Language Reference for more format elements.
SQL> create table my_test (my_date TIMESTAMP(6) WITH TIME ZONE
2 )
3 ;
Table created.
SQL> insert into my_test values (systimestamp);
1 row created.
SQL> commit;
Commit complete.
SQL> select to_char(my_date,'yyyy-mm-dd hh24:mi:ss.ff6TZH:TZM')
2 from my_test
3 ;
TO_CHAR(MY_DATE,'YYYY-MM-DDHH24:
--------------------------------
2021-03-26 14:29:21.570971-05:00
1 row selected.
SQL> --
SQL> drop table my_test purge;
Table dropped.
OK - it seems that your input is a timestamp with time zone (which is displayed to you in your "input" format, but that is irrelevant for the question).
You want to convert it to a string, in your chosen format.
This can be done as follows:
with
inputs (ts_tz) as (
select to_timestamp_tz('21-03-18 14:01:03.000000000 AMERICA/TORONTO',
'rr-mm-dd hh24:mi:ss.ff TZR')
from dual
)
select to_char(ts_tz, 'yyyy-mm-dd hh24:mi:ss.ff3tzh:tzm') as result
from inputs
;
RESULT
-----------------------------
2021-03-18 14:01:03.000-04:00
I have a column 'creation_date' which is of type 'date', when I am querying my table for distinct records based on 'creation_date' I am getting 6 records:
select distinct creation_date from test_table;
output:
06-APR-11
06-APR-11
28-MAR-11
06-APR-11
06-APR-11
18-MAR-11
In this output 6th April is displayed 4 times even when I used distinct in my query. Also when I am trying to find out all records which are matching with creation_date of 6th April 2011 I am not getting any results. Below is my query:
select * from test_table where creation_date = to_date('06-APR-11','DD-MON-YY');
Please help me where I am doing wrong in these two queries.
The problem is twofold. Firstly the dates almost definitely have time-components. to_date('06-MAR-11','DD-MON-YY') is equivalent to 2011/03/06 00:00:00. If you use the TRUNC() function you will be able to see everything for that day:
select *
from test_table
where trunc(creation_date) = to_date('06-MAR-11','DD-MON-YY');
I would not use the MON datetime format model. As I explain here it depends on your region and settings. It's safer to use a numeric month format model instead. Equally, always specify century as part of the year.
where trunc(creation_date) = to_date('06-03-YY11','DD-MM-YYYY');
Your second problem is almost definitely your NLS_DATE_FORMAT; it appears to not take into account the time, hence why you see 4 identical dates. This only governs the manner in which data is displayed not how it is stored.
You can change this using something like:
ALTER SESSION SET NLS_DATE_FORMAT = "DD/MM/YYYY HH24:MI:SS"
If I set up a test environment using the following:
create table test_table ( creation_date date );
insert into test_table values ( sysdate );
insert into test_table values ( sysdate - 0.01 );
alter session set nls_date_format = "YYYY/MM/DD";
You can see the data returned does not include time (though SYSDATE does):
SQL> select * from test_table;
CREATION_D
----------
2013/04/12
2013/04/12
Altering the NLS_DATE_FORMAT and performing the same SELECT, you now get a time component:
SQL> alter session set nls_date_format = "YYYY/MM/DD HH24:MI:SS";
Session altered.
SQL> select * from test_table;
CREATION_DATE
-------------------
2013/04/12 12:48:41
2013/04/12 12:34:17
Lastly, when trying to select today's date alone no rows will be returned:
SQL> select *
2 from test_table
3 where creation_date = to_date('20130412','yyyymmdd');
no rows selected
But, when using TRUNC() to compare on only the date portion of the field you get all your rows again:
SQL> select *
2 from test_table
3 where trunc(creation_date) = to_date('20130412','yyyymmdd');
CREATION_DATE
-------------------
2013/04/12 12:48:41
2013/04/12 12:34:17
To actually answer your second question, if you want unique dates you can re-use the TRUNC() function:
select distinct trunc(creation_date)
from test_table
The DATE datatype stores the year (including the century), the month, the day, the hours, the minutes, and the seconds (after midnight). You must also consider this.
I understand that Oracle sysdate returns the current date AND time. That's great for timestamp or datetime columns.
Now let's say I have a DATE only column. What keywords should I use on my insert query?
insert into myTable1(myDateOnlyColumn) values(???)
And let's say I have a TIME only column. What keywords should I use on my insert query?
insert into myTable2(myTimeOnlyColumn) values(???)
Thanks!
To remove time from sysdate you can just write TRUNC(sysdate).
For example:
SELECT TRUNC(SYSDATE) "TODAY" FROM DUAL;
will give you:
TODAY
-------------------------
'2012-10-02 00:00:00'
There is no such thing as a DATE only column in Oracle. The DATE datatype stores date and time.
If you only care about the date, you can:
INSERT INTO tbl (dtCol) VALUES (TO_DATE('20110929','YYYYMMDD');
This leaves the time component at 00:00:00. You don't have to display it though.
If you're only interested in the time component, you still have a date stored in the column. You'll just have to handle that on output. For example:
SQL> CREATE TABLE dt (d DATE);
SQL> INSERT INTO dt VALUES (TO_DATE('1:164800','J:HH24MISS'));
1 row inserted
Showing the actual contents of the column reveals a date was inserted:
SQL> SELECT * FROM dt;
D
--------------------
0/0/0000 4:48:00 PM
Selecting only the time component from the column gives you the output you want:
SQL> SELECT TO_CHAR(d, 'HH24:MI:SS') d FROM dt;
D
--------
16:48:00
SQL>
If you think you need only a time column, you'll want to make sure you always insert the same date component.
select sysdate, to_date(to_char(sysdate, 'dd/mm/yyyy'),'dd/mm/yyyy') d
from dual
For whoever is looking for a simple solution for returning only date without time, I found this:
to_date(SYSDATE,'dd/mm/yyyy')
Works like a charm. ;-)