Oracle Timestamp, Max and Minimal Values - oracle

I was searching, also in the Oracle Doc, for the following:
What is the range for Timestamp in Oracle?
I know for date it is -4712, Jan-01 to 9999 Dec-31, but what for Timestamp?
Anyone a clue or hint where I can search?

You can always just try it:
SQL> select to_timestamp( '9999-12-31 23:59:59', 'yyyy-mm-dd hh24:mi:ss' ) from dual;
TO_TIMESTAMP('9999-12-3123:59:59','YYYY-MM-DDHH24:MI:SS')
---------------------------------------------------------------------------
31-DEC-99 11.59.59.000000000 PM
and:
SQL> select to_timestamp( '9999-12-31 23:59:59', 'yyyy-mm-dd hh24:mi:ss' )+1 from dual;
select to_timestamp( '9999-12-31 23:59:59', 'yyyy-mm-dd hh24:mi:ss' )+1 from dual
*
ERROR at line 1:
ORA-01841: (full) year must be between -4713 and +9999, and not be 0

It would be surprising if the range for the DATE portion of a TIMESTAMP was smaller than the range for a DATE, so it should be:
-4712-01-01 00:00:00 to 9999-12-31 23:59:59.999999
That assumes no time zone; the UTC value is probably constrained to that range, but someone in an Eastern time zone might manage to see a data value on 1000-01-01 in their time zone.
It is hard to find definitive data off Oracle's site. The best I found in a casual survey was:
http://www.techonthenet.com/oracle/datatypes.php
There are probably others.
I found a quote which says:
TIMESTAMP Datatype
The TIMESTAMP datatype is an extension of the DATE datatype. It stores the year,
month, and day of the DATE datatype, plus hour, minute, and second values.

Related

Oracle sql date timestamp filter [duplicate]

This question already has answers here:
Encountering SQL Error: ORA-01843: not a valid month
(5 answers)
ORACLE - ORA-01843: not a valid month
(2 answers)
Closed 4 years ago.
My Oracle table has 1,000 observations the following 2 variables: (Both fields are varchar)
ID datecreate
ABC 24/12/2016 05:32:07
I would like to filter the dates. I tried the following but to no avail...
select *
from table
where datecreate >= to_date('01/02/2018 00:00:00', 'dd/mm/yyyy hh24:mi:ss') and
datecreate <= to_date('28/02/2018 23:59:00', 'dd/mm/yyyy hh24:mi:ss')
I keep getting the following error...
ORA-01843: not a valid month
01843. 00000 - "not a valid month"
*Cause:
*Action:
Did I miss something obvious?
Thanks
It has been emphasized several times that in databases, DATE and TIME should not be stored as strings. Yet, there are several questions raised everyday, arising solely due to this poor practice.
Note that in Oracle, datetimes can either be stored as DATE type or TIMESTAMP( with or without TIMEZONE ). The DATE type contains the time component as well.
TO_DATE function comes to our rescue in cases where date strings have to be dealt with for conversion. While using dates, it is a good practice to use standard DATE literals in 'YYYY-MM-DD' format which most DBMSes understand. ( eg:- DATE '2018-02-28' ).
Also, you need not use '28/02/2018 23:59:00' or TRUNC function for such boundary cases, when you can use DATE literals. So, your query could be rewritten as
SELECT *
FROM yourtable
WHERE TO_DATE(datecreate, 'dd/mm/yyyy hh24:mi:ss') >= DATE '2018-02-01'
AND TO_DATE(datecreate, 'dd/mm/yyyy hh24:mi:ss') < DATE '2018-02-28' + 1
or < DATE '2020-02-29' if you know that it's a leap year.
If you really want to consider till 23:59 minutes, then TIMESTAMP literals could be used with TO_TIMESTAMP function.
.. AND TO_TIMESTAMP(datecreate, 'dd/mm/yyyy hh24:mi:ss') <
TIMESTAMP '2018-02-28 23:59:00'
The default NLS_DATE_FORMAT currently is DD-MON-RR. Thus your datecreate column defined as string will be implicitly converts to that format. The value 12 is not the same as DEC, thus the error. Either you use the right format or convert it to date similar below.
select *
from tbl
where to_date(datecreate, 'dd/mm/yyyy hh24:mi:ss') >=
to_date('01/02/2016 00:00:00', 'dd/mm/yyyy hh24:mi:ss')
and to_date(datecreate, 'dd/mm/yyyy hh24:mi:ss') <=
to_date('28/02/2018 23:59:00', 'dd/mm/yyyy hh24:mi:ss')

Oracle - Converting a UTC timestamp to a localtime (GMT/BST) timestamp

I have to create convert a datetime as UTC into localtime (GMT/BST)
The dates in the database are UTC AND the database is set to UTC.
I believe I can get the offset between UTC and (say) BST using TZ_OFFSET, but how can I then use that to convert the UTC datetime into a BST datetime?
So, for example, if the database (UTC) datetime is
'2018-04-03 14:30:00'
And the offset is '+01:00'
I would expect the result to be
'2018-04-03 15:30:00'
If there an elegant way of doing this? Rather than using grungy arithmetic (which then has to take into account midnight, end of month, end of year etc.)
Thanks
Use FROM_TZ to create a TIMSTAMP WITH TIME ZONE, then the conversion is very simple, for example:
FROM_TZ({your column}, 'UTC') AT TIME ZONE 'Europe/London'
As you can see in the documentation:
Example of Converting Time Zones With the AT TIME ZONE Clause:
SELECT FROM_TZ(CAST(TO_DATE('1999-12-01 11:00:00',
'YYYY-MM-DD HH:MI:SS') AS TIMESTAMP), 'America/New_York')
AT TIME ZONE 'America/Los_Angeles' "West Coast Time"
FROM DUAL;
West Coast Time
----------------------------------------------------------
01-DEC-99 08.00.00.000000 AM AMERICA/LOS_ANGELES
So, applied to your case scenario:
SELECT FROM_TZ(CAST(TO_DATE('2018-04-03 14:30:00',
'YYYY-MM-DD HH24:MI:SS') AS TIMESTAMP), 'UTC')
AT TIME ZONE 'GMT' "Greenwich Mean Time"
FROM DUAL;
Greenwich Mean Time
----------------------------------------------------------
03-APR-18 02.30.00.000000 PM GMT
You can get the list of available timezones with:
SELECT tzname, tzabbrev FROM V$TIMEZONE_NAMES;
If you have a table YOUR_TABLE with a column some_timestamp:
create table YOUR_TABLE (
some_timestamp timestamp
);
/
insert into YOUR_TABLE (
SOME_TIMESTAMP
) values (
CAST(TO_DATE('2018-04-03 14:30:00', 'YYYY-MM-DD HH24:MI:SS') AS TIMESTAMP)
);
Then you can run:
select
SOME_TIMESTAMP,
FROM_TZ(SOME_TIMESTAMP, 'UTC') AT TIME ZONE 'GMT' "Greenwich Mean Time",
FROM_TZ(SOME_TIMESTAMP, 'UTC') AT TIME ZONE 'Europe/London' "London Time"
from YOUR_TABLE;
SOME_TIMESTAMP Greenwich Mean Time London Time
----------------------------------------------------------
03-APR-18 02.30.00.000000 PM 03-APR-18 02.30.00.000000 PM GMT 03-APR-18 03.30.00.000000 PM EUROPE/LONDON
And if you are absolutely sure that your server is in UTC, as well as the timestamps introduced, then you can skip that UTC conversion part:
select
SOME_TIMESTAMP,
SOME_TIMESTAMP AT TIME ZONE 'GMT' "Greenwich Mean Time",
SOME_TIMESTAMP AT TIME ZONE 'Europe/London' "London Time"
from YOUR_TABLE;
it should be pretty simple::
select datetimecolumn + INTERVAL '1' HOUR from mytable
hope i understand your requirement correctly.

Use time in between in oracle for multiple date

Select *
from mytable
where paid_time Between to_date('00:00:00','HH24:MI:SS' ) and to_date('00:59:59','HH24:MI:SS')
and paid_date Between to_date('1/8/2016','DD/MM/RRRR') and
to_date('10/8/2016','DD/MM/RRRR');
Note :
1. I need perticular time period only for 10 days
Error :
1. data is there but returning Zero kindly help to solve this
You need to use the full date and time TO_DATE otherwise there is conflicting WHERE clauses'DD/MM/RRRR hh24:mi:ss'.
SELECT *
FROM mytable
WHERE paid_time BETWEEN TO_DATE('01/08/2016 00:00:00', 'DD/MM/RRRR hh24:mi:ss') AND TO_DATE('10/08/2016 00:59:59', 'DD/MM/RRRR hh24:mi:ss');
If paid_time is a string then your query will only work at all for certain NLS_DATE_FORMAT settings, due to the implicit conversion you are forcing:
alter session set nls_date_format = 'RRRR-MM-DD';
with mytable (paid_date, paid_time) as (
select date '2016-08-02', '00:01:02' from dual
)
Select *
from mytable
where paid_time Between to_date('00:00:00','HH24:MI:SS' ) and to_date('00:59:59','HH24:MI:SS')
and paid_date Between to_date('1/8/2016','DD/MM/RRRR') and
to_date('10/8/2016','DD/MM/RRRR');
no rows selected
alter session set nls_date_format = 'YYYY-MM-DD';
-- same query
ORA-01841: (full) year must be between -4713 and +9999, and not be 0
alter session set nls_date_format = 'DD/MM/RRRR';
-- same query
ORA-01847: day of month must be between 1 and last day of month
... etc.
When you do to_date('00:00:59','HH24:MI:SS') the generated date defaults to the first of the current month, so when run today it will get a September date:
select to_char(to_date('00:00:59','HH24:MI:SS'), 'YYYY-MM-DD HH24:MI:SS') from dual;
TO_CHAR(TO_DATE('00
-------------------
2016-09-01 00:00:59
You are then trying to compare your paid_time string with that date, which means the string is implicitly converted to a date using your NLS settings, e.g.:
alter session set nls_date_format = 'RRRR-MM-DD';
select to_char(to_date('00:01:02'), 'YYYY-MM-DD HH24:MI:SS') from dual;
TO_CHAR(TO_DATE('00
-------------------
2000-01-02 00:00:00
So your filter is really looking for rows where the time string, incorrectly converted to a date (exactly which date depends on your actual NLS setting, and many values will error whatever the setting), is in the first minute of the first day of the current month. Which is very unlikely to ever match anything.
If it is a string and is always formatted consistently then you can just compare as a string:
with mytable (paid_date, paid_time) as (
select date '2016-08-02', '00:01:02' from dual
)
Select *
from mytable
where paid_time Between '00:00:00' and '00:59:59'
and paid_date Between to_date('1/8/2016','DD/MM/RRRR') and
to_date('10/8/2016','DD/MM/RRRR');
PAID_DATE PAID_TIM
---------- --------
2016-08-02 00:01:02
As mentioned in comments Oracle's data datatype includes the time, so storing the date (at midnight, presumably) and the time in separate columns just adds complexity and inefficiency.

Alter a datetime in Oracle and set time to 9 am

i have 28-APR-2016 10:05:07 date as parameter in stored procedure. This may be the current time also as string date.
i need to set the time to 9 am to check the shift start timing.
SELECT TO_DATE('28-APR-2016 10:05:07', 'DD-MON-YYYY HH24:MI:SS') FROM dual;
I am new to oracle. Help is appreciated.
If you want the date with 9:00 a.m., then you can do:
SELECT TRUNC(TO_DATE('28-APR-2016 10:05:07', 'DD-MON-YYYY HH24:MI:SS')) + 9/24.0
FROM dual;
You can also use:
SELECT TRUNC(TO_DATE('28-APR-2016 10:05:07', 'DD-MON-YYYY HH24:MI:SS')) + INTERVAL '9' HOUR
FROM dual;
I'm just old-fashioned so I tend to use the first method.

Date function on oracle

I've got a question about date function on oracle.
I have the following table
statistic_table(
pages AS varchar(10),
date_created AS date
);
I have the following sql
SELECT COUNT(*) FROM statistic_table WHERE date_created BETWEEN sysdate-5 AND sysdate-1
and
SELECT COUNT(*) FROM statistic_table WHERE date_created BETWEEN to_date('12-AUG-2011') AND to_date('16-AUG-2011');
the question is, why is it return different numbers. assuming sysdate-5 returns 12-aug-2011 and sysdate-1 returns 16-aug-2011
Any help would be much appreciated!
Cheers,
sysdate - 5 will give you a date with the current time. So if I ran it at 1pm precisely, the query would be equivalent to:
select (*)
FROM statistic_table
WHERE date_created BETWEEN to_date('12-Aug-2011 13:00:00')
AND to_date('16-Aug-2011 13:00:00')
whereas the second query is:
select (*)
FROM statistic_table
WHERE date_created BETWEEN to_date('12-Aug-2011 00:00:00')
AND to_date('16-Aug-2011 00:00:00')
you should probably try this instead:
select (*)
FROM statistic_table
WHERE date_created BETWEEN trunc(sysdate) -5
AND trunc(sysdate) -1
A date in Oracle is a point in time with a precision of a second.
SYSDATE returns the current date and time and is therefore not the same as to_date('17-AUG-2011'):
SQL> SELECT to_char(sysdate, 'dd-mon-yyyy hh24:mi:ss') FROM DUAL;
TO_CHAR(SYSDATE,'DD-MON-YYYYHH
------------------------------
17-aug-2011 15:52:13
Use the TRUNC function if you only want the date component:
SQL> SELECT to_char(trunc(sysdate), 'dd-mon-yyyy hh24:mi:ss') FROM DUAL;
TO_CHAR(TRUNC(SYSDATE),'DD-MON
------------------------------
17-aou-2011 00:00:00
Because SYSDATE includes a time component, so if the current time is 11:22:33, then
SELECT COUNT(*) FROM statistic_table
WHERE date_created BETWEEN sysdate-5 AND sysdate-1
is actually equivalent to
SELECT COUNT(*) FROM statistic_table
WHERE date_created BETWEEN to_date('12-AUG-2011 11:22:33','DD-MON-YYYY HH24:MI:SS')
AND to_date('16-AUG-2011 11:22:33','DD-MON-YYYY HH24:MI:SS')
To avoid the time component do this:
SELECT COUNT(*) FROM statistic_table
WHERE date_created BETWEEN TRUNC(sysdate)-5 AND TRUNC(sysdate)-1
An Oracle DATE always has a day and a time component.
sysdate-5 returns a date exactly 5 days ago. If today is August 17 at 10 AM, for example, sysdate-5 returns August 12 at 10 AM.
to_date('12-AUG-2011', 'DD-MON-YYYY'), on the other hand, returns August 12 at midnight. So it returns a date that is 10 hours earlier than sysdate-5.
sysdate auto returns with a time component as mentioned by the previous answers.
When using to_date it is converting a string to a date. With this being said you can pass in parameters to make it return the same thing.
Have a look at this link that explains it.
to_date parameters

Resources