string to timestamp conversion plsql - oracle

I've inherited some data from an external source which is a timestamp. This was put into warehouse by someone as a varchar2. I need to convert this to a legitimate timestamp but am unsure how. This is how the string looks. "2021-04-23T11:02:17.00Z".
Would appreciate some help.
PS Ideally, I'd also like to know how to trunc this to a more traditional date format of DD-MMM-YYYY e.g. 21-Jan-2021 or even DD-MM-YYYY is fine.

Use to_timestamp_tz() to get the corresponding timstamp with time zone, convert it to the timezone you want it in (for example sessiontimezone) with AT TIME ZONE and cast() that to a timestamp.
SELECT cast(to_timestamp_tz('2021-04-23T11:02:17.00Z', 'YYYY-MM-DD"T"HH24:MI:SS.FF2:TZR') AT TIME ZONE sessiontimezone AS timestamp)
FROM dual;
db<>fiddle

Shouldn't be too difficult. Extract the "date" part, apply TO_DATE function to it (with appropriate format mask) and - that's all. It means that you should "stop" at the date_value in the following query. The last, final_result is a string again, just formatted as you wanted.
SQL> with test (col) as
2 (select '2021-04-23T11:02:17.00Z' from dual)
3 select substr(col, 1, 10) string,
4 --
5 to_date(substr(col, 1, 10), 'yyyy-mm-dd') date_value,
6 --
7 to_char(to_date(substr(col, 1, 10), 'yyyy-mm-dd'), 'dd-mm-yyyy') final_result
8 from test;
STRING DATE_VALUE FINAL_RESU
---------- ---------- ----------
2021-04-23 2021-04-23 23-04-2021
SQL>
In order to avoid that "operation", you might even create a view. For example:
This is a table you currently have:
SQL> create table test as
2 (select 1 id, 'Littlefoot' name, '2021-04-23T11:02:17.00Z' col from dual);
Table created.
Create a view, re-using code I posted above:
SQL> create or replace view v_test as
2 select id, name,
3 to_date(substr(col, 1, 10), 'yyyy-mm-dd') col
4 from test;
View created.
Select from it:
SQL> select * from v_test;
ID NAME COL
---------- ---------- ----------
1 Littlefoot 2021-04-23
Want another format? No problem:
SQL> alter session set nls_date_format = 'dd-mon-yyyy';
Session altered.
SQL> select * from v_test;
ID NAME COL
---------- ---------- -----------
1 Littlefoot 23-apr-2021
SQL>
Or, apply TO_CHAR to view's col column (also demonstrated in code I posted first; see the final_result).

You can use the TO_TIMESTAMP function to do this.
Try:
TO_TIMESTAMP('2021-04-23T11:02:17.00Z', 'YYYY-MM-DDTHH:MI:SS')
You can read more about this function in their Documentation

Related

Charts in Oracle Apex

Hi everyone I wanna ask u about how I can bring data last 24 hours into bar charts, is there any methods to make it please
I have this table without data
datetime
clientchannel
servicename
service_count
13_02_2022 9:35
*****
notification
2
It is a WHERE clause you need, I presume. Something like this:
select ...
from your_table
where datetime >= sysdate - 1;
Why? Because - when you subtract a number from DATE datatype value in Oracle - it subtracts that many days.
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
SQL> select sysdate right_now,
2 sysdate - 1 yesterday
3 from dual;
RIGHT_NOW YESTERDAY
------------------- -------------------
13.02.2022 11:01:34 12.02.2022 11:01:34
SQL>
If you store date values as strings (which means that DATETIME column is declared as e.g. VARCHAR2(20), and that's really bad idea), then you first have to convert it to a valid date datatype value - use TO_DATE function with appropriate format mask:
where to_date(datetime, 'dd_mm_yyyy hh24:mi') >= sysdate - 1
[EDIT] If you want to go 60 minutes back, then subtract that many minutes:
SQL> select sysdate right_now,
2 sysdate - interval '60' minute an_hour_ago
3 from dual;
RIGHT_NOW AN_HOUR_AGO
------------------- -------------------
14.02.2022 07:09:30 14.02.2022 06:09:30
SQL>

Insert Birthdate with only YY format for period before 2000 Oracle DB

I have afile where i recieve Birthdates and insert them into my Database.
the format is like the following
03-JUN-52
I use the following script to insert the date
update data."PersonBDates" set BIRTHDATE = to_date('13-SEP-47', 'DD-MON-YY');
and i also used
update data."PersonBDates" set BIRTHDATE = to_date('13-SEP-47', 'DD-MON-RR');
but when i check if find it 2074 not 1947.
How to insert this date into my oracle database?
Generally speaking, RR should work, but - not in all cases. You'll have to fix data first because RR will return different values:
for years from 00 to 49 you'll get this century, 20xx, while
50 to 99 will return previous century, 19xx
Here's an example:
SQL> alter session set nls_date_format = 'dd.mm.yyyy';
Session altered.
SQL> select
2 to_date('03-07-52', 'dd-mm-rr') rr1,
3 to_date('03-07-52', 'dd-mm-yy') yy1 ,
4 --
5 to_date('03-07-47', 'dd-mm-rr') rr2,
6 to_date('03-07-47', 'dd-mm-yy') yy2
7 from dual;
RR1 YY1 RR2 YY2
---------- ---------- ---------- ----------
03.07.1952 03.07.2052 03.07.2047 03.07.2047
SQL>
As you can see, both RR and YY format mask for year 47 return 2047.
What to do? Concatenate 19 to all years, e.g.
SQL> with test (col) as
2 (select '03-07-52' from dual union all
3 select '03-07-47' from dual
4 )
5 select col,
6 to_date(substr(col, 1, 6) || '19' || substr(col, -2), 'dd-mm-rrrr') result
7 ---------------- ---------------
8 -- this is "03-07-" "19" the last 2 digits
9 --
10 from test;
COL RESULT
-------- ----------
03-07-52 03.07.1952
03-07-47 03.07.1947
SQL>
[EDIT]
If your current inserting script works OK - which I doubt, regarding error code you mentioned in a comment:
ORA-01858: a non-numeric character was found where a numeric was expected
which means that not all input data have the same, expected & correct format of DD-MON-YY, then a simple way to fix birthdates might be this:
subtract 100 years from all dates whose year is larger than 2000
Here's how:
SQL> create table test (birthdate date);
Table created.
SQL> insert into test
2 select to_date('03-07-52', 'dd-mm-rr') from dual union all
3 select to_date('03-07-47', 'dd-mm-rr') from dual;
2 rows created.
SQL> select * from test;
BIRTHDATE
----------
03.07.1952
03.07.2047
SQL> update test set
2 birthdate = add_months(birthdate, -100 * 12)
3 where extract (year from birthdate) > 2000;
1 row updated.
SQL> select * from test;
BIRTHDATE
----------
03.07.1952
03.07.1947
SQL>
You can modify that, of course, if there's someone who actually was born in 2000 or later.
As of error you got (ORA-01858), well, fixing it depends on how exactly you're entering those values into a table.
if it was a SQL*Loader, invalid values would be rejected and stored into the .bad file and you could fix them and reprocess them later
if it was using an external tables, you could use a where clause and omit invalid rows; for example, use regexp_like
Or, your best option is to make sure that all input values are valid dates. Then any option you choose (I mentioned previously) would work without ORA-xxxxx errors.
Alternate way of concatenating 19 to all years, as Littlefoot suggested.
to_date(regexp_replace('13-SEP-47', '([0-9]+$)', '19\1'), 'DD-MON-YYYY')
I would suggest to implement the solution where 01 is not considered as 1901 but 2001 or something similar (I assume that birthday year is not 1901 for any person in your system).
Case when substr(col, -2) < to_char(sysdate,'YY')
then to_date(col, 'DD-MON-YY')
else to_date(substr(col, 1, 6) || '19' || substr(col, -2), 'dd-mm-rrrr'
End
Cheers!!

How to convert DATETIME in specific format to DATE in PL/SQL

I apologize for asking a simple question, but I could not find the answer on the forum.
I need to convert from this datetime '2009-06-18T00:00:00+06:00' to format 'YYYY-MM-DD' in PL/SQL.
If this "datetime" is really a timestamp (as it looks like), not a string, then you can choose how to display it (using TO_CHAR) or convert to DATE (using TO_DATE), or simply TRUNCATE it. Note that the last two results (i.e. the way they are displayed) depend on current NLS settings (set by my ALTER SESSION).
Here's an example:
SQL> alter session set nls_date_format = 'dd.mm.yyyy';
Session altered.
SQL> with test
2 as (select to_timestamp_tz ('2009-06-18T00:00:00+06:00',
3 'yyyy-mm-dd"t"hh24:mi:ss tzh:tzm')
4 col
5 from dual)
6 select to_char (col, 'yyyy-mm-dd') res1,
7 to_date (to_char (col, 'yyyy-mm-dd'), 'yyyy-mm-dd') res2,
8 trunc (col) res3
9 from test;
RES1 RES2 RES3
---------- ---------- ----------
2009-06-18 18.06.2009 18.06.2009
SQL>
Use TO_DATE on the first 10 characters in your timestamp string:
SELECT TO_DATE(SUBSTR('2009-06-18T00:00:00+06:00', 1, 10), 'YYYY-MM-DD') FROM dual
Demo
Documentation is the best part.
http://www.sqlines.com/oracle-to-sql-server/to_date
you can use the TO_DATE(string, format) function for that so it will be like
SELECT TO_DATE('2012-06-05', 'YYYY-MM-DD') FROM xyz;
DEPENDS on the data type.
If the column is DATE data type, then, as suggested already, TRUNC would do the job to display. But, if your locale-specific NLS date settings are different, then you will still see the time portion as midnight.
Else, you need to use TO_DATE with proper FORMAT and apply TRUNC to it.
update
If you only want to display, use TO_CHAR, else, if you have a filter in your WHERE clause, then remember TO_CHAR doesn't return DATE, it converts it into literal.

Using a case when to know if date format is right

I want to migrate a table which contains some columns with dates. The issue is my dates are often in dd/mm/yyyyy HH24:MM:YYYY format. But sometimes it appears that the format is only dd/mm/yyyy, or blank.
I guess that's why I'm getting ORA-01830 when I'm trying to migrate the datas.
I tried
CASE
WHEN TO_DATE(MYDATE,'DD/MM/YYYY')
then TO_DATE(MYDATE,'DD/MM/YYYY 00:00:00')
END AS MYDATE
But I'm not sure if it is possible to test the date format (and ofcourse it's not working).
Thank you
TO_DATE cannot test date format, but you can do it. If Lalit's answer would not be enough, try something like
select
case when my_date like '__/__/__' then to_date(my_date, 'dd/mm/yy')
when my_date like '__-__-__' then to_date(my_date, 'dd-mm-yy')
...
end
So you have the data type issue. DATE is stored as string literal. As you have mentioned that the date model has the DD/MM/YYYY part same, just that the time portion is either missing for some rows or the entire value is NULL.
For example, let's say your table have the values like -
SQL> WITH dates AS(
2 SELECT 1 num, '29/12/2014 16:38:57' dt FROM dual UNION ALL
3 SELECT 2, '29/12/2014' FROM dual UNION ALL
4 SELECT 3, NULL FROM dual
5 )
6 SELECT num, dt
7 FROM dates
8 /
NUM DT
---------- -------------------
1 29/12/2014 16:38:57
2 29/12/2014
3
SQL>
TO_DATE with proper format model should do the trick.
Let's stick to a format model first.
SQL> alter session set nls_date_format='dd/mm/yyyy hh24:mi:ss';
Session altered.
Now, let's use TO_DATE to explicitly convert the string literal to date.
SQL> WITH dates AS(
2 SELECT 1 num, '29/12/2014 16:38:57' dt FROM dual UNION ALL
3 SELECT 2, '29/12/2014' FROM dual UNION ALL
4 SELECT 3, NULL FROM dual
5 )
6 SELECT num, to_date(dt, 'dd/mm/yyyy hh24:mi:ss') dt
7 FROM dates
8 /
NUM DT
---------- -------------------
1 29/12/2014 16:38:57
2 29/12/2014 00:00:00
3
SQL>

Oracle: How to convert the following date to a different format:

in my select query i have the following
substr(to_date(NEXT_ARRIVAL_DATE, 'yyyy-mm-dd'), 0, 10)
Which yields:
08-JUN-11
What i need is it to yield:
2011-06-08
EDIT:
The data was coming in wrong. sorry. The below workds fine
to_char(to_date(NEXT_ARRIVAL_DATE, 'mm/dd/yyyy'), 'YYYY-MM-DD') || ' 00:000:00'
Your DATE_NEXT_ARRIVAL column obviously has a date datatype.
SQL> create table t23 (next_arrival_date date)
2 /
Table created.
SQL> insert into t23 values (sysdate+7)
2 /
1 row created.
SQL> select to_date(next_arrival_date, 'YYYY-MM-DD')
2 from t23
3 /
TO_DATE(N
---------
11-JUN-08
SQL>
If you want to display the date in a different format you need to use TO_CHAR() i.e. convert it to a string:
SQL> select to_char(next_arrival_date, 'YYYY-MM-DD')
2 from t23
3 /
TO_CHAR(NE
----------
2011-06-08
SQL>
If you have to do this for a whole bunch of dates, you might want to change the session settings instead....
SQL> alter session set nls_date_format='YYYY-MM-DD'
2 /
Session altered.
SQL> select sysdate, next_arrival_date
2 from t23
3 /
SYSDATE NEXT_ARRIV
---------- ----------
2011-06-01 2011-06-08
SQL>
in Oracle you can convert a DATE column to string with
to_char(NEXT_ARRIVAL_DATE, 'yyyy-mm-dd')
but it looks like the value of NEXT_ARRIVAL_DATE is a string in the required format.
so you can just do select NEXT_ARRIVAL_DATE from ...

Resources