Storing timestamp values stored in a varchar2 column into a date column in oracle - oracle

I have a column in a table that stores timestamp values as
"2018-01-12 16:13:51.107000000", i need to insert this column into a date column in another table, what format mask do i have to use here..
I have used the mask 'YYYY-MM-DD HH24:MI:SS.FF' but shows 'date format not recognized'.

I am assuming that you were trying to use TO_DATE on your text timestamp data. This won't work, because Oracle dates do not store anything more precise than seconds. Since your timestamps have fractional seconds, you may use TO_TIMESTAMP here, then cast that actual timestamp to a date:
SELECT
CAST(TO_TIMESTAMP('2018-01-12 16:13:51.100000',
'YYYY-MM-DD HH24:MI:SS.FF') AS DATE)
FROM dual;
12.01.2018 16:13:51
Demo

You can do this with a single call to TO_DATE(), but you must give the correct format model. Note that this solution is simpler (and possibly faster - if that matters) than converting to a timestamp and then casting to date.
If you want TO_DATE() to ignore part of the input string, you can use the "boilerplate text" syntax in the format model. That is enclosed in double quotes. For example, if your string included the letter T somewhere and it had to be ignored, you would include "T" in the same position in the format model.
This has some flexibility. In your case, you must ignore the decimal point, and up to nine decimal digits (the maximum for timestamp in Oracle). The format model will allow you to use ".999999999" (or any other digits, but 9999... is used by most programmers) to ignore a decimal point and UP TO nine digits after that.
Demo: (notice the double-quoted "boilerplate text" in the format model)
select to_date('2018-01-12 16:13:51.100000',
'YYYY-MM-DD HH24:MI:SS".999999999"') as dt
from dual;
DT
-------------------
2018-01-12 16:13:51

Related

How to make a constraint on DATE FORMAT in ORACLE

say my usual Date format is '14-jan-2019' and i want my date to only be accepted as 'YYYY-MM-DD' how do i do that? and can i change jan to an actual number?
In my opinion, the right / correct way to do that is to declare your date column (or variable or whatever it is) as DATE, e.g.
create table test (date_column date);
or
declare
l_date_variable date;
begin
...
Doing so, you'd let the database take care about valid values.
You'd then be able to enter data any way you want, using any valid date format mask, e.g.
to_date('06.01.2020', 'dd.mm.yyyy')
date '2020-01-06'
to_date('2020-06-01', 'yyyy-dd-mm')
etc. - all those values would be valid.
A DATE data type has no format - it is stored internally as 7-bytes representing year (2 bytes) and month, day, hour, minute and second (1 byte each).
'14-JAN-2019' is not a date - it is a text literal.
If you want to store date values then use a DATE data type.
If you want to only accept strings of a specific format as input then in whatever user interface you use to talk to the database then accept only that format. If you are converting strings to DATEs and wanting an exact format then you can use:
TO_DATE( '2019-01-14', 'fxYYYY-MM-DD' )
Note: the fx format model will mean that the exact format is expected and the typical string-to-date conversion rules will not be applied.

Varchar to Timestamp but varchar data is yyyy-mm-dd-hh:mi:ss:ff format

My source is from Oracle and the col1 is varchar2(26) but the value looks like YYYY-MM-DD-hh:mi:ss:ff (Sample rec: 2014-08-15-02.03.34.979946).
I have to extract only 6 months records based on COL1. Since there is a hypen between date part and time part - i could not consider as timestamp. Is there any idea how to have this as timestamp to lookup only 6 months data.
If it is possible at all, fix the data first. Storing timestamps in string data type is terrible. How do you know you don't have a time like 25:30:00 in the strings? Or a date like February 30? Besides, you can't really use an index on that column (so queries will be very slow), you will have to write a lot of code whenever referencing that column, etc.
Anyway - to deal with the immediate problem, use TO_TIMESTAMP(), exactly with the format model you show in your post - including the dash between the date part and the time part. Something like this:
select case when to_timestamp('2014-08-15-02.03.34.979946', 'YYYY-MM-DD-HH24:MI:SS.FF')
>= systimestamp - interval '6' month
then 'TRUE' else 'FALSE' end
as result
from dual;
RESULT
------
FALSE
EDIT: As Alex Poole points out (correctly as always) in a Comment below this Answer, interval arithmetic won't work correctly in all cases. It is better, than, to use something like
cast ( timestamp (...., format-model) as date ) <= add_months (sysdate, -6).
Maybe something like this will do:
select *
from your_table
where to_date(substr(col1,1,19),'yyyy-mm-dd-HH24.MI.SS') between add_months(sysdate,-6) and sysdate;
Assuming all the data format in col1 is always the same.
Also note that I used HH24 for hour segment, however could be not your case.
You can include the dash in your format model, as #mathguy showed, to convert your string to a timestamp:
select to_timestamp('2014-08-15-02.03.34.979946', 'YYYY-MM-DD-HH24:MI:SS.FF') from dual;
TO_TIMESTAMP('2014-08-15-02.
----------------------------
15-AUG-14 02.03.34.979946000
although unless you explicitly tell it not to be via the FX modifier, Oracle is flexible enough to allow a dash even if the model has a space (see the text below this table in the documentation:
select to_timestamp('2014-08-15-02.03.34.979946', 'YYYY-MM-DD HH24:MI:SS.FF') from dual;
TO_TIMESTAMP('2014-08-15-02.
----------------------------
15-AUG-14 02.03.34.979946000
However, converting all of the values in your col1 column and then comparing them may be a lot of work, and will prevent any index on that string column being used. Given the format, you can convert your date range to string instead, and use string comparison; e.g. to find everything in the six months up to midnight this morning:
select col1 -- or whichever columns you need
from your_table
where col1 >= to_char(cast(add_months(trunc(sysdate), -6) as timestamp), 'YYYY-MM-DD-HH24:MI:SS.FF6')
and col1 < to_char(cast(trunc(sysdate) as timestamp), 'YYYY-MM-DD-HH24:MI:SS.FF6');
or since the time part can be fixed for that example, you can use character literals instead of casting:
select col1 -- or whichever columns you need
from your_table
where col1 >= to_char(add_months(sysdate, -6), 'YYYY-MM-DD"-00:00:00.000000"')
and col1 < to_char(sysdate, 'YYYY-MM-DD"-00:00:00.000000"');
Of course, storing data in the correct native data type would be a much better solution. Any other solution only works at all if your string data actually contains what you think, and the data is all sane (or as sane as it can be in the wrong data type).

Oracle - Date Format

I need your assistance with converting Oracle dates.
I have a column that stores dates like this 20150731 00:00:34.220. However, I would like to show the column like this 20150731 but when I run a simple select statement to test output I get the following error.
select TO_DATE('20150731 00:00:34.550','YYYYMMDD')
from dual
Error
ORA-01830: date format picture ends before converting entire input string
This query
select TO_DATE('20150731 00:00:34.550','YYYYMMDD')
from dual
leads to error
ORA-01830: date format picture ends before converting entire input string
because you pass string with length 22 characters, but at the same time you pass date format with 8 characters, which obviously doesn't correspond to string. You should write the query as
select to_timestamp('20150731 00:00:34.550','yyyymmdd hh24:mi:ss.ff3')
from dual
As for your table, since you have varchar2 column with dates, you have to take care about table content. Query requires exect matching of the source string and date format.
If you want to show only date without time and you don't need to process this string as date, you can make just
select substr('20150731 00:00:34.550', 1, 8)
from dual
What is the data type of the column? If it is DATE (as it should be) then not it is not stored in the format you say. It is stored in an internal binary format. You would/should use the to_char function to DISPLAY it in whatever format you choose. If you do not use the to_char function, it will be displayed in the format specified by NLS_DATE_FORMAT, which can be specified at several locations.
As for your example, you passed a string format of yyyymmd hh:mi:ss.fff', but you provided a description mask of only YYYYMMDD. It doesn't know what to do with time component. In addition to that when you SELECT TO_DATE, oracle also has to do an implied TO_CHAR to convert it back to a string for display purposes.
In addition, you provided your to_date with a character string that included fractions of seconds. A DATE data type only resolves to seconds. If you need fractional seconds, you need to use TIMESTAMP, not DATE.
If your column is a varchar and you need a date output:
select TO_DATE(substr('20150731 00:00:34.550', 1, 8),'YYYYMMDD') from dual
If it's in a date format and you need a string output:
select to_char(your_column, 'YYYYMMDD') from your_table
Is that being stored in an Oracle datetime column? If not, you may have to do some manipulation to get it into a DD-MON-YYYY format. If it is being stored as a text string you could use SUBSTR( Date_field, Start_Position, Length) to get the first 8 characters. check out this link SUBSTR
Working on the assumption that you're not trying to change the value in the column, and are just trying to show it in the YYYYMMDD format -
As mentioned by a_horse_with_no_name, you'll just need to convert it to a character string. In this example I used systimestamp as my date:
SELECT TO_CHAR(systimestamp,'YYYYMMDD') FROM DUAL
Result:
20160121
That should give you the YYYYMMDD format you want to display.

How to change default date,timestamp dataype for columns in oracle

I have created a table in Oracle in which I have KPI_START_DATE column which is a Date datatype, and KPI_START_TIME which is a TIMESTAMP datatype.
Now I want to modify this date dataype for
KPI_START_DATE to dd/mm/yyyy
and
KPI_START_TIME to HH:MI:SS.
So that user should always enter the date and time in this column in this proper format.
I tried below query but its was giving error:
Alter table KPI_DEFINITION MODIFY(to_char(KPI_START_DATE,'dd/mm/yyyy') )
DATE and TIMESTAMP columns do not have any inherent readable format. The values are stored in Oracle's own internal representation, which has no resemblance to a human-readable date or time. At the point to retrieve or display a value you can convert it to whatever format you want, with to_char().
Both DATE and TIMESTAMP have date and time components (to second precision with DATE, and with fractional seconds with TIMESTAMP; plus time zone information with the extended data types), and you should not try to store them separately as two columns. Have a single column and extract the information you need at any time; to get the information out of a single column but split into two fields you could do:
select to_char(KPI_START, 'dd/mm/yyyy') as KPI_START_DATE,
to_char(KPI_START, 'hh24:mi:ss') as KPI_START_TIME
but you'd generally want both together anyway:
select to_char(KPI_START, 'dd/mm/yyyy hh24:mi:ss')
Also notice the 'hh24' format model to get the 24-hour clock time; otherwise you wouldn't see any difference between 3 a.m. and 3 p.m.
You can store a value in either type of column with the time set to midnight, but it does still have a time component - it is just midnight. You can't store a value in either type of column with just a time component - it has to have a date too. You could make that a nominal date and just ignore it, but I've never seen a valid reason to do that - you're wasting storage in two columns, and making searching for and comparing values much harder. Oracle even provides a default date if you don't specify one (first day of current month). But the value always has both a date and a time part:
create table KPI_DEFINITION (KPI_START date);
insert into KPI_DEFINITION (KPI_START)
values (to_date('27/01/2015', 'DD/MM/YYYY'));
insert into KPI_DEFINITION (KPI_START)
values (to_date('12:41:57', 'HH24:MI:SS'));
select to_char(KPI_START, 'YYYY-MM-DD HH24:MI:SS') from KPI_DEFINITION;
TO_CHAR(KPI_START,'YYYY-MM-DDHH24:MI:SS')
-----------------------------------------
2015-01-27 00:00:00
2015-01-01 12:41:57
Your users should be inserting a single value with both date and time as one:
insert into KPI_DEFINITION (KPI_START)
values (to_date('27/01/2015 12:41:57', 'DD/MM/YYYY HH24:MI:SS'));
select to_char(KPI_START, 'YYYY-MM-DD HH24:MI:SS') from KPI_DEFINITION;
TO_CHAR(KPI_START,'YYYY-MM-DDHH24:MI:SS')
-----------------------------------------
2015-01-27 12:41:57
You can also use date or timestamp literals, and if using to_date() you should always specify the full format - don't rely on NLS settings as they may be different for other users.
You should understand difference between datatype and format. DATE is a datatype. TIMESTAMP is a datatype. None of them have formats, they're just numbers.
When converting character datatype to or from date datatype, format should be applied. It's an attribute of an actual conversion, nothing else.
Look at this:
SQL> create table tmp$date(d date);
Table created
SQL> insert into tmp$date values (DATE '2010-11-01');
1 row inserted
SQL> insert into tmp$date values (DATE '2014-12-28');
1 row inserted
SQL> select d, dump(d) from tmp$date;
D DUMP(D)
----------- ---------------------------------
01.11.2010 Typ=12 Len=7: 120,110,11,1,1,1,1
28.12.2014 Typ=12 Len=7: 120,114,12,28,1,1,1
There is no any 'format' here.
DISPLAYING and STORING are NOT the same when it comes to DATE.
When people say Oracle isn’t storing the date in the format they wanted, what is really happening is Oracle is not presenting the date in the character string format they expected or wanted.
When a data element of type DATE is selected, it must be converted from its internal, binary format, to a string of characters for human consumption. The conversion of data from one type to another is known as known a “conversion”, “type casting” or “coercion”. In Oracle the conversion between dates and character strings is controlled by the NLS_DATE_FORMAT model. The NLS_DATE_FORMAT can be set in any of several different locations, each with its own scope of influence.
I could go on with my leacture over DATE data type, but I am glad that someone has already got a good writeup over this. Please read this https://edstevensdba.wordpress.com/2011/04/07/nls_date_format/

how to insert iso-8601 type date into oracle database

I am using Oracle 11g and trying to figure out how to insert this date into my table. The date seems like it is ISO-8601, but the 7 zeros are confusing me.
Insert into myTestTable (myDate) values ('2013-01-22T00:00:00.0000000-05:00');
I have tried to format the date with no luck. The error I am getting is ORA-01861 literal does not match format string.
First of all, the column must be a TIMESTAMP WITH TIME ZONE type to hold the value you're trying to insert. An Oracle DATE is accurate to seconds only, and it doesn't hold a time zone.
The seven zeros are the fractional seconds. The default precision for a TIMESTAMP WITH TIME ZONE happens to be seven decimal places. To specify three decimal places for seconds, define the column as TIMESTAMP(3) WITH LOCAL TIME ZONE.
The actual number of decimal places returned by SYSTIMESTAMP, which is the current timestamp at the server, depends on the operating system. My local Windows 7 Oracle returns three significant decimal places, while the Solaris OS at one of my clients returns six significant decimal places.
As for inserting the value, if you do something like this...
insert into myTestTable (myTS) values ('2013-01-22T00:00:00.0000000-05:00');
... Oracle will try to convert the timestamp using its current NLS_TIMESTAMP_TZ_FORMAT setting. You can query the setting like this:
SELECT *
FROM NLS_Session_Parameters
WHERE Parameter = 'NLS_TIMESTAMP_TZ_FORMAT';
PARAMETER VALUE
----------------------- ----------------------------
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR
The result I got is the "factory default". Yours is probably the same, and you can see it doesn't match the format you've given, hence the conversion fails.
As another answer correctly notes, you can use the TO_TIMESTAMP_TZ function and a format string to convert the string to a timestamp. You can also use an ANSI timestamp literal:
insert into myTestTable (myTS)
values (TIMESTAMP '2013-01-22T00:00:00.0000000-05:00');
Oracle documents timestamp literals here. The link covers literals for all types, so you'll need to scroll about two-thirds of the way down the screen (or do a find) to get to the timestamp literals.
Here is the answer.
insert into myTestTable (myDate) values
(to_timestamp_tz('2013-01-22T00:00:00.0000000-05:00',
'YYYY-MM-DD"t"HH24:MI:SS.FF7TZR'));

Resources