I need a query to update a time in an appointment date by keeping the date but changing the time.
For example
10-Feb-2016 09:00:00
and i want to change it to 10-Feb-2016 10:00:00.
Update Appointment
set vdate = '10:00:00'
where vdate= '10-Feb-2016'
I get the "0 row has been updated'. Not sure if i'm missing something.
Thanks in advance.
You can use trunc() which sets the time part of a DATE (or TIMESTAMP) to 00:00:00, then add the 10 hours to it:
Update Appointment
set vdate = trunc(vdate) + interval '10' hour
where trunc(vdate) = DATE '2016-02-10'
This would change all rows that have a date 2016-02-10. If you only want to do that for those that are at 09:00 (ignoring the minutes and seconds) then just add one hour to those rows
Update Appointment
set vdate = trunc(vdate) + interval '1' hour
where trunc(vdate, 'hh24') = timestamp '2016-02-10 09:00:00'
trunc(vdate, 'hh24') will set the minutes and seconds of the date value to 00:00, so that the comparison with 2016-02-10 09:00:00 works properly.
Unrelated, but: do not rely on implicit data type conversion. '10-Feb-2016' is a string value, not a DATE literal. To specify a date either use an ANSI DATE literal (as I have done in the above statement) or use the to_date() function with a format mask to convert a string literal to a proper date value.
Your statement is subject to the evil implicit data type conversion and will fail if the SQL client running the statement uses a different NLS setting (it will fail on my computer for example)
If what you want to do is add an hour to a date, then you can do:
Update Appointment
set vdate = vdate + 1/24
where vdate = to_date('10/02/2016 09:00', 'dd/mm/yyyy hh24:mi');
since in Oracle, date differences are measured in number of days, and an hour is 1/24th of a day.
If what you want to do is specify an exact time (e.g. to 10:25:48), then you could do the following instead:
Update Appointment
set vdate = trunc(vdate) + 10/24 + 25/(24*60) + 48/(24*60*60)
where vdate = to_date('10/02/2016 09:00', 'dd/mm/yyyy hh24:mi');
Bear in mind that these updates will update all rows that have a date of 10th Feb 2016 at 9am. You'd need to change your query's where clause if you wanted to specify a more specific row or set of rows.
Try like this.
UPDATE MyTable
SET MyDate = DATEADD(HOUR, 4, CAST(CAST(MyDate AS DATE) AS DATETIME))
or
UPDATE MyTable
SET MyDate = DATEADD(HOUR, 4, CAST(FLOOR(CAST(MyDate AS FLOAT)) AS DATETIME))
Related
select (current_date - TO_DATE('20210817124015','YYYYMMDDHH24MISS')) from dual;
Outputs:
0.1229282407407407407407407407407407407407
I want to know how oracle internally achieves this value.
ps: the current_date and the hardcoded date are same, only time is the difference.
CURRENT_DATE returns the current date and time in the user's session time zone.
TO_DATE('20210817124015','YYYYMMDDHH24MISS') returns the date 2021-08-17T12:40:15.
Note: A DATE data type always has year, month, day, hour, minute and second components. However, the user interface you are using may chose not to show all the components.
Subtracting one date from another returns the number of days between the two values.
0.1229282407407407407407407407407407407407 days is:
2.950277778 hours; or
177.016666667 minutes; or
10621 seconds; or
2 hours 57 minutes and 1 second.
So your current date was 2021-08-17T12:40:15 + 10621 seconds or 2021-08-17T15:37:16.
For example:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD"T"HH24:MI:SS';
ALTER SESSION SET TIME_ZONE = 'Asia/Samarkand';
SELECT CURRENT_DATE,
TO_DATE('20210817124015','YYYYMMDDHH24MISS') As other_date,
CURRENT_DATE - TO_DATE('20210817124015','YYYYMMDDHH24MISS') as difference,
(CURRENT_DATE - TO_DATE('20210817124015','YYYYMMDDHH24MISS')) DAY TO SECOND
as interval_difference
FROM DUAL;
Outputs:
CURRENT_DATE
OTHER_DATE
DIFFERENCE
INTERVAL_DIFFERENCE
2021-08-17T15:40:01
2021-08-17T12:40:15
.124837962962962962962962962962962962963
+00 02:59:46.000000
db<>fiddle here
Subtracting two dates returns a difference in days.
0.1229282407407407407407407407407407407407 days is
2.9502777777768 hours
177.016666666608 minutes
10621 seconds
Or, put another way, current_date is returning a date value that is 2 hours 57 minutes and 1 second after the hard-coded date. Since the hard-coded date has a time of 12:40:51, that means that current_date has a time of 15:37:52.
I am unable to get the date column to respect the where clause. Regardless what I do, it does not filter on date. I have tried all combinations of to_char and to_date in vain.
HAVING TO_CHAR(PAYMASTR.CHECK_DATE,'MM/DD/YYYY') > '01/01/2021'
I have also tried the code below with all combinations of to_char and to_date.
HAVING PAYMASTR.CHECK_DATE >= TO_DATE('01-01-2021 12:00:00 AM',
'MM-DD-YYYY HH:MM:SS AM')
The check_date of of type DATE.
Result set:
|COMPANY|EMPLOYEE|PAY_SUM_GRP|PAY_GRADE RATE|WAGE_AMOUNT|NET_PAY_AMT|GROSS_PAY|CHECK_DATE|
|-------|--------|-----------|--------------|-----------|-----------|---------|----------|
|2|5|REG 09|21.98|175.84|1459.96|2263.19|1/19/2007 12:00:00 AM|
|2|5|REG 09|21.98|175.84|1663.93|2589.43|1/5/2007 12:00:00 AM|
If CHECK_DATE column's datatype is DATE (should be! If it is VARCHAR2, you're doing it wrong!), then
having check_date > date '2021-01-01'
i.e. compare date to date literal.
Second code you posted is almost OK:
HAVING PAYMASTR.CHECK_DATE >= TO_DATE('01-01-2021 12:00:00 AM', 'MM-DD-YYYY HH:MI:SS AM')
--
MI for minutes; MM is for month
I found this article on code project that did the trick for me. I was struggling really hard to get the query to respect the date parameter in the queru. Setting the session to NLS_DATE_FORMAT worked. Not sure what other implications it may have. Will have to talk to the DBA.
Code Project
It's all about how Oracle stores and works with date DATATYPE
The date has seven components
Century, year, month, day, hour, minute, seconds
and all these components take seven bytes of storage.
Whenever you fetch a Date column from a table, the date value is formatted in a more readable form and this format is set in the nls_date_format parameter.
I am assuming you are grouping by CHECK_DATE otherwise you need to add this date filter with the WHERE clause.
So first check the datatype of your column CHECK_DATE
If it is date then
HAVING CHECK_DATE >= TO_DATE('01-01-2021', 'MM-DD-YYYY')
You don't have to provide hours, minutes, and seconds if omitted hours are rounded to 12 AM or 00 if the 24-hour format is used;
Or if you want to have hours as well then you used MM instead of MI for minutes.
HAVING CHECK_DATE >= TO_DATE('01-01-2021 00:00:00', 'MM-DD-YYYY HH24:MI:SS')
And this does not make sense
HAVING TO_CHAR(PAYMASTR.CHECK_DATE,'MM/DD/YYYY') > '01/01/2021'
You want to compare dates not characters and to_char will provide you a character string that has no sense of comparing with another string '01/01/2021'.
So if you are not grouping by CHECK_DATE user filter condition with WHERE clause
or check the datatype of CHECK_DATE if it is not DATE change it to DATE.
I'm trying to get a new date from the product of 'date' + 'time interval'.
Something like this.
'15/02/2016 18:00:00' + '+00 02:00:00.000000'
Expected result:
'15/02/2016 20:00:00'
But using the columns in database.
CREATE TABLE timerest
(
DATE_ASIGN DATE,
TIME_ASIGN INTERVAL DAY(2) TO SECOND(0)
);
Thanks for your help.
You can just add them together:
insert into timerest (date_asign, time_asign)
values (to_date('15/02/2016 18:00:00', 'DD/MM/YYYY HH24:MI:SS'),
to_dsinterval('+00 02:00:00.000000'));
alter session set NLS_DATE_FORMAT = 'DD/MM/YYYY HH24:MI:SS';
select date_asign + time_asign from timerest;
DATE_ASIGN+TIME_ASIGN
---------------------
15/02/2016 20:00:00
This follows the rules for datetime/interval arithmetic: date + interval = date.
If you have a date in DATE format you can simply add the a numeric interval that represents days (for example 1.5 is 1 day and a half)
You can extract from the time interval days and hours and then add them to to you date because, if I remember correctly, you can't add directly them to a date type (maybe to a timestamp type you can)
To extract the days you can use the extract function:
(
extract(second from TIME_ASIGN)/3600)+(extract(hour from TIME_ASIGN)/24)+(extract(day from TIME_ASIGN)/24)
then you add the number to your DATE_ASIGN
How can i convert the result of select statement of time interval field in respective time in Am/Pm format.
My Field is:
Interval Day(2) To Second(6)
I tried this:
select To_Char(Att_EntranceTime , 'HH:MI AM') From EMPLOYEEATTENDENCETABLE;
however this does not help me, i have also tried to add the basetime from systime to my interval field but that did not help.. can someone suggest me what to do?
Intervals can't be directly formatted, as you've discovered. You can add your interval to any date which has its time set to midnight, and then format the resulting date to show the time in your desired format. For example you could add it to today's date using trunc(sysdate):
to_char(trunc(sysdate) + my_interval, 'HH:MI AM')
You need to truncate it to set the time to midnight; otherwise the result will be your interval plus the current system time.
Or you can use any fixed date; here's an example with some dummy data set-up:
create table my_table (my_interval interval day(2) to second(6));
insert into my_table (my_interval) values (interval '0 12:34:56.78' day to second);
insert into my_table (my_interval) values (interval '99 01:02:03.456' day to second);
select my_interval, to_char(date '1970-01-01' + my_interval, 'HH:MI AM') as formatted
from my_table;
MY_INTERVAL FORMATTED
-------------------- ---------
+00 12:34:56.780000 12:34 PM
+99 01:02:03.456000 01:02 AM
The second value shows a potential problem. Your interval is defined to allow a two-digit day number, which means the interval can span anything less than 100 days. If you only extract the time portion you lose that information about the number of days. That may be what you want to happen though. If the interval is supposed to be representing a time of day, which wanting to show AM/PM implies - and it's unusual to store an actual time separate from its date - then having or allowing a number of days seems strange.
I've got a report I'm writing in BIRT against an Oracle database:
Table:
tranx_no (string)
type (string)
description (string)
amount (number(14,2))
date (date)
Query in BIRT:
SELECT tranx_no, type, description, amount
FROM tranx_table
WHERE date BETWEEN ? AND ?
If I just do plain dates (02-01-2014 and 02-14-2014) in the parameters, it misses things that happen during the day of the 14th (stops at midnight). I've tried concatenating the time onto the date parameter
WHERE date BETWEEN ? || '12:00:00 AM' AND ? || '11:59:59 PM'
and got an ORA 01843 error. I also tried casting it with to_date
WHERE date BETWEEN TO_DATE(? || '12:00:00 AM', 'MM-DD-YYYY HH:MI:SS AM') AND TO_DATE(? || '11:59:59 PM', 'MM-DD-YYYY HH:MI:SS AM')
and no joy there either. ORA 01847 error happens with that one.
Ideas? I know there's probably something simple I'm not thinking of, but Google hasn't helped. I'm wanting to edit the query, not change the date entry on the face of the form.
Thanks.
Correct handling DATEs with BIRT can be tricky.
I recommend to always use VARCHAR2 for passing DATE parameters (for report parameters as well as for query parameters). Always verify the data type of your parameters.
In your SQL, always use TO_DATE / TO_CHAR with an explicit date format - otherwise the results would depend on the locale settings.
Next, be sure that the value the user entered is adjusted to a known date-format before it is used in the query. For example, in Germany the SQL date format DD.MM.YYYY HH24:MI:SS is commonly used.
You could create a utility function which adds the missing parts (e.g. the time) automatically. Use an additional argument in this function to specify if it's a "from" date (adds 00:00:00) or a "to" date (adds 23:59:59).
OTOH if the UI forces the user to enter a from-to date without time (say in the format 'MM-DD-YYYY' as in your example), you could just code
WHERE (date >= to_date(?, 'MM-DD-YYYY') and date < to_date(?, 'MM-DD-YYYY') + 1)
Note the usage of < and not <=.
This works because if no time is specified in the format mask, 00:00:00 (in HH24:MI:SS format) is implied.
As you pointed out the start date is not a problem as it begins at 00:00:00 of the start date. If your paramter is a text box your users can enter 02-01-2014 08:00:00 to get results starting at 8am on Feb 1.
Note that my date format has the year first, while yours has the year last
For the end date, I use a text box paramater with this as my default value
//Creates a date for one second before midnight of the current date,
//which is properly formatted to use as an end date in quires (for my data)
// Note that a custom date format (yyyy-MM-dd HH:mm:ss) is required for proper display in pop-up GUI
var T; T = BirtDateTime.addDay(BirtDateTime.today(),1);
var Y; Y = BirtDateTime.year(T);
var M; M = BirtDateTime.month(T);
var D; D = BirtDateTime.day(T);
{
Y +"-"
+ M +"-"
+ D +" "
+"00:00:00"
}
I also use this help text
Enter date as YYYY-MM-DD. For example, 2013-3-14
Adn this prompt text
End Date (YYYY-MM-DD), if time is blank will default to 00:00:00