Oracle virtual column, date and timestamp - oracle

I have a problem in Oracle, with a virtual column (I need the timestamp starting from a date column); here my example:
CREATE TABLE TBDATETIME(
DATETIME_1 DATE,
DATETIME_2 TIMESTAMP(9) GENERATED ALWAYS AS (
CAST( TO_CHAR(DATETIME_1, 'DD/MM/YYYY HH24:MI:SS')
|| '.' || TO_CHAR(DATETIME_1, 'FF9') AS TIMESTAMP(9))
) VIRTUAL
);
INSERT INTO TBDATETIME(DATETIME_1)
VALUES(SYSDATE);
COMMIT;
SELECT *
FROM TBDATETIME;
ORA-01821: date format not recognized
01821. 00000 - "date format not recognized"
*Cause:
*Action:
Where is the problem fetching data? I tried a lot of format masks, but nothing helps...

DATETIME_1 DATE
TO_CHAR(DATETIME_1, 'FF9')
That's the problem - DATE doesn't have fraction seconds
And it's dangerous to cast char to timestamp (the result depends on nls settings)
I suppose you want this:
CREATE TABLE TBDATETIME(DATETIME_1 DATE, DATETIME_2 TIMESTAMP(9) GENERATED ALWAYS AS (CAST(DATETIME_1 AS TIMESTAMP(9))) VIRTUAL);

Related

year value in table in oracle

I have this query in oracle:
DELETE FROM my_table
WHERE to_date(last_update, 'DD/MM/YYYY') < to_date('01/01/2000', 'DD/MM/YYYY');
when I run this, I get this error:
ORA-01841: (full) year must be between -4713 and +9999 and must not be 0
there is not any 0 value in the table.
any one knows what is the problem?
I am assuming that you have stored your dates as a string with the DD/MM/YYYY format; it would be better if you stored them all as a DATE data type and then you would not have to do this conversion (and you would be using the most appropriate data type for the data).
From Oracle 12, you can use:
SELECT *
FROM my_table
WHERE TO_DATE( last_update, 'DD/MM/YYYY' DEFAULT NULL ON CONVERSION ERROR ) IS NULL;
To identify the rows that are raising that exception.
If you are already storing them as a DATE data type then don't use TO_DATE on a value that is already a DATE as TO_DATE expects a string so Oracle will implicitly cast your DATE to a string and then try to convert it back and your query is effectively:
DELETE FROM my_table
WHERE TO_DATE(
TO_CHAR(
last_update,
( SELECT value FROM NLS_SESSION_SETTINGS WHERE PARAMETER = 'NLS_DATE_FORMAT' )
),
'DD/MM/YYYY'
) < to_date('01/01/2000', 'DD/MM/YYYY');
And if the NLS_DATE_FORMAT and your format model do not match then you will get errors (or, worse, the query will succeed and your data will be inconsistent as it may have swapped days and months or months and years).
Instead, just use:
DELETE FROM my_table
WHERE last_update < DATE '2000-01-01';
If the datatype of last_update is date, don't use the to_date function:
DELETE FROM my_table
WHERE last_update < to_date('01/01/2000', 'DD/MM/YYYY');

Fetch Hours from Created date

I'm just trying to fetch Hour of my table from created date in Oracle 12c Database but it is showing error INVALID EXTRACT FIELD FOR EXTRACT FIELD. kindly guide me to fetch hour of my date my code is here...
SELECT
EXTRACT( HOUR FROM (TO_CHAR(CREATED_DATE,'RRRR-MM-DD HH:MI:SS')) ) HOUR
FROM
INVOICE_V;
my Date is stored as 6/1/2020 4:04:50 PM in this format and Extract function is not accept this function.
Do not store dates as strings.
But, since you have, convert it from a string to a date using TO_DATE:
SELECT EXTRACT( HOUR FROM TO_TIMESTAMP(CREATED_DATE,'DD/MM/YYYY HH12:MI:SS AM') ) AS HOUR
FROM INVOICE_V;
If, however, you meant that its just displaying in that format (and is actually a DATE data type) then CAST the date to a timestamp:
SELECT EXTRACT( HOUR FROM CAST( CREATED_DATE AS TIMESTAMP) ) AS HOUR
FROM INVOICE_V;
An hour can not be used in the EXTRACT function.
The only way to extract hour is to use TO_CHAR or subtract it from TRUNC date as follows:
TO_CHAR(created_date,'HH24') -- OR 'HH' as per your requirement
-- OR
FLOOR(24*(created_date- TRUNC(created_date)))
Please note that Oracle does not store dates in any format. It has its own binary representation. What you see while selecting from the table is based on the NLS_DATE_FORMAT parameter.
You can set it according to your requirement.
ALTER SESSION SET NLS_dATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'; -- like this
If you have a date column (or the-like), then:
select extract(hour from cast(created_date as timestamp)) as hr
from invoice_v
Alternatively:
select to_char(created_date, 'hh24') as hr
from invoice_v
The first expression returns an integer number, while the second produces a string.
Note that hour is a language keyword, hence not a good choice for an identifier (here, you used it as a column alias). I changed that.

Invalid date format in datatype column in BODS job to Oracle

I am using SAP BODS and I am trying to fetch data from an ORACLE server using SQL query transormation. Now The table has a column named latest_changed_date which is a datetime column. I only want yesterday and current day data from that table. Now since the column is datetime, I need to convert it to date, but when I am using to_date function I get the following error.
SELECT *
FROM ABC.TEST
WHERE TO_DATE(LATEST_CHANGED_DATE) = TO_DATE(SYSDATE-1)
The database error message is
ORA-01843: not a valid month
I tried giving date format in TO_DATE condition as below:
SELECT *
FROM ABC.TEST
WHERE TO_DATE(LATEST_CHANGED_DATE,'YYYY-MM-DD') >= TO_DATE(SYSDATE-1,'YYYY-MM-DD')
Here I got the error:
date format picture ends before converting entire input string
I used trunc function also and again got either:
not a valid month
or
inconsistent datatypes: expected NUMBER got DATE
Below is a sample data for the column. I just need data for current and day before data from the column.
Update: I think the main issue is that I am not able to determine the proper datatype for the column in the source table and currently I don't have an option to determine that.
Rather than trying to implicitly cast your dates to strings and convert them back using TO_DATE( string_value, format_model ) you can use TRUNC() to truncate SYSDATE to the start of the day:
SELECT *
FROM ABC.TEST
WHERE LATEST_CHANGED_DATE >= TRUNC( SYSDATE-1 )
this will work:
SELECT *
FROM ABC.TEST
where sysdate-LATEST_CHANGED_DATE<=sysdate-(sysdate-2);
for example take this:
ALTER SESSION SET NLS_DATE_FORMAT = ' DD-MON-YYYY HH24:MI:SS';
SELECT * FROM d061_dates ;
03-DEC-2018 17:44:38
25-AUG-2018 17:44:42
30-AUG-2018 17:44:46
01-DEC-2018 17:44:49
02-DEC-2018 17:46:31
SELECT * FROM d061_dates
where sysdate-a<=sysdate-(sysdate-2);
03-DEC-2018 17:44:38
02-DEC-2018 17:46:31
you have to take sysdate minus on both sides to get comparision by a number which is less than equal to 2 to get day and day before yesterday and its giving the correct output.
thank you!!!!!!!!!!!!!

Between not included the end date in oracle

I am writing the query like
select * from tablename where date between '27-mar-2015' and '1-apr-2015'.
but records with date '1-apr-2015' is not retrieved from the oracle database date type is TIMESTAMP(6).
between '27-mar-2015' and '1-apr-2015'
'27-mar-2015' is NOT a DATE, it is a string literal. You are forcing Oracle to do an implicit datatype conversion.
date type is TIMESTAMP(6)
Since your data type is TIMESTAMP, you need to take care of the precision of the TIMESTAMP datatype which holds fractions of a second to a precision between 0 and 9 decimal places, the default being 6.
BETWEEN
to_timestamp('27-mar-2015 01.01.01.000001','dd-mon-yyyy HH24:MI:SS.FF')
AND
to_timestamp('01-apr-2015 23.59.59.999999','dd-mon-yyyy HH24:MI:SS.FF')
For example,
SQL> ALTER SESSION SET nls_timestamp_tz_format = 'DD-MON-YYYY HH24:MI:SS.FF';
Session altered.
SQL> SELECT
2 to_timestamp('27-mar-2015 01.01.01.000001','dd-mon-yyyy HH24:MI:SS.FF') st,
3 to_timestamp('01-apr-2015 23.59.59.999999','dd-mon-yyyy HH24:MI:SS.FF') end
4 FROM dual
5 /
ST END
---------------------------------- ----------------------------------
27-MAR-15 01.01.01.000001000 AM 01-APR-15 11.59.59.999999000 PM
SQL>
You have to note that timestamp-columns (and with oracle even date-columns) always include the time of day and that date '1-apr-2015' actually means '1-apr-2015 00:00:00' - then everything makes sense. The exact string-representation of timestamps might vary according to the configured locale.
To get date including the first of april you best use between ... and '2-apr-2015' if you don't mind having the first microsecond of that day included.
Try convert to_date:
select * from tablename
where date between to_Date('27-mar-2015','dd-mm-yyy')
and to_date('1-apr-2015','dd-mm-yyyy')
I have faced same issue. Using TRUNC Date Function helped.
select * from tablename where trunc(date,'DAY') between '27-mar-2015' and '1-apr-2015'
Try to use this code:
select * from tablename where to_date(date,'DD-MON-YYYY') between '27-mar-2015' and '1-apr-2015'.

What must be considered when modifying Oracle DATE column to TIMESTAMP

The system I'm working on uses an oracle 11 db and has a java implemented backend which uses JDBC.
The system has one main performance problem:
The oracle db has indexed DATE columns but the java backend access the db like this
String sql = "SELECT foo FROM bar WHERE a_date > ?";
// ... prepare the statement
statement.setTimestamp(1, new Timestamp());
then Oracle will not use the index and fall back to full table scan because of statement.setTimestamp.
First Solution:
So I have changed the access of the backend from statement.setTimestamp to statement.setDate.
The performance has been improved and the DATE index was now used, but now I lost the accuracy of the timestamp data type, and only got a day-accuracy of the java.sql.Date type.
Thus, the first solution was unusable for my system.
Second Solution:
I don’t change the java backend thus using statement.setTimestamp and change all DATE columns of the oracle db like the following sql command example:
ALTER TABLE <table_1> MODIFY <date_column> TIMESTAMP;
Now my question:
What must be considered when modifying Oracle DATE column to TIMESTAMP
I think a list of the important aspects would be perfect.
Here my first draft of the "CHECKLIST of Migrating Oracle DATE columns to TIMESTAMP
1. CREATE / INSERT
2. READ / SELECT
3. UPDATE / UPDATE
4. DELETE / DELETE
5. TO_DATE( )
select * from table where crea_time between TO_DATE( '10.2014', 'MM.yyyy' ) and TO_DATE( '12.2014', 'MM.yyyy' ) ;
6. TRUNC( )
select TRUNC( crea_time ) from table;
output of crea_time data typ DATE
05.11.2014 00:00:00
output of crea_time data typ TIMESTAMP
05.11.2014 00:00:00
7. TO_CHAR( )
select to_char( crea_time,'hh24miss' ) from table;
output data typ DATE
140612
output data typ TIMESTAMP
140612
8. NESTED - TRUNC( TO_DATE() )
select TRUNC(TO_DATE( crea_time), 'YEAR') from table;
output of crea_time data typ DATE
01.01.2014 00:00:00
output of crea_time data typ TIMESTAMP
ORA-01830:
01830. 00000 - "date format picture ends before converting entire input string"
*Cause:
*Action:
Solution >>> select TRUNC( TO_TIMESTAMP( crea_time), 'YEAR' ) from table;
output of crea_time data typ TIMESTAMP
01.01.2014 00:00:00
9. Add A DAY/HOUR/MINUTE/SECOND
select crea_time+1 from table;
output data typ DATE
06.11.2014 14:06:12
output data typ TIMESTAMP
06.11.2014 14:06:12
10. MIN() / MAX()
SELECT MIN(crea_time) FROM table;
output data typ DATE
05.11.2014 14:06:12
output data typ TIMESTAMP
05.11.2014 14:06:12,000000000
Please excuse my bad English.

Resources