Oracle TIMESTAMP Comparison with TO_TIMESTAMP function - oracle

I am having a problem getting the result I expect from an Oracle query.
The TO_TIMESTAMP I am using appears to work fine:
SELECT TO_TIMESTAMP('11-16-2014 00:00:00', 'mm-dd-yyyy hh24:mi:ss') FROM DUAL
Returns
2014-11-16 00:00:00
My table AUDIT has a column CURRENT_TIMESTAMP of Oracle type TIMESTAMP(6). I don't know if it helps but this column also has these attributes:
DATATYPE=93
COLUMN_SIZE=11
DECIMAL_DIGITS=6
NUM_PREC_RADIX=10
CHAR_OCTET_LENGTH=11
Lets look at the table size:
SELECT count(*) FROM RPT.AUDIT
returns
623981
This table grows about 500 rows a day. So I would expect this query to return a number under 1000.
Instead I get the whole table:
SELECT count(*) FROM RPT.AUDIT WHERE CURRENT_TIMESTAMP > TO_TIMESTAMP('11-16-2014 00:00:00', 'mm-dd-yyyy hh24:mi:ss')
returns
623981
Thanks if you can help.

Because CURRENT_TIMESTAMP is the name of an Oracle function the database prefers to use the function instead of your column - and thus, since CURRENT_TIMESTAMP (the function) is always greater than a time in the past the predicate returns TRUE for every row in the table, and thus every row gets counted. If you put a table alias in your query and qualify the column name with the alias you should get what you expected:
SELECT count(*)
FROM RPT.AUDIT a
WHERE a.CURRENT_TIMESTAMP > TO_TIMESTAMP('11-16-2014 00:00:00', 'mm-dd-yyyy hh24:mi:ss')
Or you can just refer to the column as RPT.AUDIT.CURRENT_TIMESTAMP if you like.
Share and enjoy.

Related

Oracle: Why do I have to use TO_DATE to pull my data?

When trying to filter on EXPIRE_DATE, it seems I have to use TO_DATE. Why do I have to use TO_DATE? The EXPIRE_DATE data type in the database is ALREADY set to date. Here is the code that works.
SELECT * FROM MY_TABLE
WHERE EXPIRE_DATE >= TO_DATE('2020/01/13','yyyy/mm/dd')
AND EXPIRE_DATE <= TO_DATE('2020/04/19','yyyy/mm/dd')
I tried to use BETWEEN without TO_DATE and just use my dates but I received an error.
To recap, even though the data type for this is ALREADY date, it seems I have to use TO_DATE to pull my data when I want to filter. Is there something I am missing? Here is my error when I try filter my data without using TO_DATE.
Apart from some good answers here, I would like to tell you that you do not need TO_DATE to pull the data from your table.
You need to_date or date literal to convert the normal string to date which can be compared to the column data in your table, As the date column must be compared with the date data type variable/constant.
To convert normal string to date, You can use the following:
TO_DATE('2020/01/13','yyyy/mm/dd')
DATE '2020-01-13'
I would not recommend using NLS_DATE_FORMAT just for creating the date.
You don't need to use TO_DATE, instead you can use a DATE literal:
SELECT *
FROM MY_TABLE
WHERE EXPIRE_DATE >= DATE '2020/01/13'
AND EXPIRE_DATE <= DATE '2020/04/19'
Or, if your NLS_DATE_FORMAT session parameter matches YYYY/MM/DD then you can insert the values as strings and rely on implicit string conversion (don't do this though):
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY/MM/DD';
SELECT *
FROM MY_TABLE
WHERE EXPIRE_DATE >= '2020/01/13'
AND EXPIRE_DATE <= '2020/04/19'
But it is not good practice to rely on the NLS_DATE_FORMAT as ANY user can change their own value at ANY time so your query can randomly fail when users start changing these values.
You can use BETWEEN:
Warning: it's better to use always TO_DATE function with proper format string and avoid implicit conversions that in some occasions produces strange behaviors in the results.
Warning: all columns of type DATE have always the hour-minute-second component.
if you forget this you may have fewer records in the result.
Example:
create table my_table
(id number,
expire_date date
);
Some data:
insert into my_table values ( 4,to_date('2011-06-17 10:07:18','yyyy-mm-dd hh24:mi:ss'));
insert into my_table values (12,to_date('2010-10-01 17:43:30','yyyy-mm-dd hh24:mi:ss'));
insert into my_table values (13,to_date('2011-07-30 08:38:34','yyyy-mm-dd hh24:mi:ss'));
insert into my_table values (21,to_date('2010-04-22 07:03:35','yyyy-mm-dd hh24:mi:ss'));
insert into my_table values (26,to_date('2011-03-26 02:07:57','yyyy-mm-dd hh24:mi:ss'));
insert into my_table values (35,to_date('2010-09-16 17:40:01','yyyy-mm-dd hh24:mi:ss'));
insert into my_table values (38,to_date('2011-11-05 17:27:45','yyyy-mm-dd hh24:mi:ss'));
insert into my_table values (44,to_date('2011-12-25 04:51:24','yyyy-mm-dd hh24:mi:ss'));
insert into my_table values (45,to_date('2011-11-05 03:08:51','yyyy-mm-dd hh24:mi:ss'));
insert into my_table values (54,to_date('2011-09-22 18:29:14','yyyy-mm-dd hh24:mi:ss'));
insert into my_table values (78,to_date('2010-03-12 20:23:21','yyyy-mm-dd hh24:mi:ss'));
insert into my_table values (79,to_date('2011-05-19 17:30:15','yyyy-mm-dd hh24:mi:ss'));
insert into my_table values (83,to_date('2011-11-15 10:04:58','yyyy-mm-dd hh24:mi:ss'));
insert into my_table values (96,to_date('2011-03-11 20:14:30','yyyy-mm-dd hh24:mi:ss'));
Set default date format to ISO-8601 international format:
alter session set nls_date_format='YYYY-MM-DD HH24:MI:SS';
Query using implicit conversion:
SELECT a.*
fROM my_table a
where expire_date between '2010-01-01 00:00:00'
and '2010-12-31 23:59:59';
Answer:
ID EXPIRE_DATE
12 2010-10-01 17:43:30
21 2010-04-22 07:03:35
35 2010-09-16 17:40:01
78 2010-03-12 20:23:21
but using US date format month-day-year:
SELECT a.*
fROM my_table a
where expire_date between '01/01/2010 00:00:00'
and '12/31/2010 23:59:59';
You got error:
ORA-01861: literal does not match format string
Change session date format to US format:
alter session set nls_date_format='MM-DD-YYYY HH24:MI:SS';
you can write dates in US format:
SELECT a.*
fROM my_table a
where expire_date between '01/01/2010 00:00:00'
and '12/31/2010 23:59:59';
And the answer is:
ID EXPIRE_DATE
---------- -------------------
12 10-01-2010 17:43:30
21 04-22-2010 07:03:35
35 09-16-2010 17:40:01
78 03-12-2010 20:23:21

Oracle query not giving result for current_date

What is the query in Oracle to fetch the data for current_date
the column end_date is like the following
end_date
27-10-16 03:35:00.000000000 PM
23-11-16 11:15:00.000000000 AM
02-11-16 03:00:00.000000000 PM
08-11-16 09:00:00.000000000 AM
Like I am running the following query as
Select * from table1
where end_date < TO_DATE('2017-04-11 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
it is running successfully, but when i replace the query with the current date ... it is not giving the results
Select * from table1
where end_date < TO_DATE(current_date, 'YYYY-MM-DD HH24:MI:SS')
could someone tell me what is the cause the second query is not giving results.
CURRENT_DATE returns date. There is no need to use TO_DATE. The below query should be enough.
Select * from table1
where end_date < current_date;
If you run the below query you'll understand what went wrong for you. Year becomes 0011.
SELECT TO_DATE(current_date, 'YYYY-MM-DD HH24:MI:SS') FROM DUAL;
Please note that CURRENT_DATE returns the current date in the session time zone. SYSDATE returns the current date and time set for the operating system on which the database resides. This means that CURRENT_DATE and SYSDATE can return different results. You can have a look at this
The query worked like this :
Select * from table1
where trunc(end_date) < trunc(sysdate)
Trunc is used to compare the both dates and it fetch the results.
CURRENT_DATE is already a DATE value. You can format the output using to_char if you want.
end_date < CURRENT_DATE should do the job. Or you can set the nls parameter accordingly for a better readability.
If you are comparing only date, without timestamp, you can go with trunc()

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.

Oracle: Select Milliseconds from Timestamp Type that Defaults with SYSTIMESTAMP

I have a column with TIMESTAMP type in my Oracle Database. The default column value is SYSTIMESTAMP.
I want to SELECT milliseconds FROM the TIMESTAMP column. I use the query below without success:
SELECT TO_CHAR (MY_TIMESTAMP, 'dd-mm-yyyy hh24:mi:ss.FF') AS MY_TIMESTAMP
FROM MY_TABLE
-- Result: 20-12-2015 15:23:28.
As you see the result does not have any milliseconds and it is empty. If I change the query with .FF4 then it results .0000.
How can I SELECT the column with milliseconds?
The precision for timestamp columns can be set up by
TIMESTAMP [(fractional_seconds_precision)].
In your case for 4 it's:
create table my_table
(id number,
my_TIMESTAMP timestamp(4) default SYSTIMESTAMP);
You can check your current precision by:
select column_name, data_scale from user_tab_columns
where table_name = 'MY_TABLE' and column_name = 'MY_TIMESTAMP';
Here is sample in SQL Fiddle
The display can be change by:
alter session set NLS_TIMESTAMP_FORMAT = 'DD-MON-RRRR HH:MI:SS.FF9';

Inserting timestamp in oracle timestamp column

I have a table in which there is a column with datatype TIMESTAMP(0)
When I insert a date into this column using
INSERT INTO TEST_TIMESTAMP VALUES(SYSDATE)
it inserts a date in the following example format
12-SEP-12 10.31.19.000000000 AM
I want to know how the below timestamp formats can be inserted in the table
12-SEP-12 10.31.19 and 12-SEP-12 10.31.19 AM
I tried specifying some formats using TO_CHAR while inserting SYSDATE into the table, but it didn't work.
Please suggest.
when you store a TIMESTAMP it will always store the data at maximum precision (with fractional seconds).
I think what you want to do is supply a format to display the date when you retrieve it from the database.
You can do this like so:
select to_char(timestampColumnName,'DD-MON-YY HH24:MI:SS') "Date" from test_timestamp
or
select to_char(timestampColumnName,'DD-MON-YY HH:MI:SS AM') "Date" from test_timestamp
You can return it very easy like:
SELECT to_char(sysdate,'DD-MON-YY HH24:MI:SS') FROM DUAL;
In your case use:
INSERT INTO TEST_TIMESTAMP(column_name) VALUES(to_char(sysdate,'DD-MON-YY HH24:MI:SS'));
You were missing the extra ().
INSERT INTO TEST_TIMESTAMP
VALUES (TO_TIMESTAMP('12-SEP-12 10.31.19', 'DD-MON-YY HH.MI.SS'));
INSERT INTO TEST_TIMESTAMP
VALUES (TO_TIMESTAMP('12-SEP-12 10.31.19 AM', 'DD-MON-YY HH.MI.SS AM'));
TO_CHAR(SYSDATE, 'DD/MM/YYYY HH24:MI:SS')
This for colum type insert over mode to_char.

Resources