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

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!!

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>

string to timestamp conversion plsql

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

How to convert time to number in Oracle SQL

I have a column with time datatype like for example:
01:00
24:00
03:00
I need to convert this time to number so it will be like
0100
2400
0300
First, Oracle does not have a "time" datatype. If you are working with a date or a timestamp datatype, you can use the TO_CHAR function to format the time portion of the data in whatever style you want. The following would return the style you describe, using HH24 to convert hours to the hour format and MI to return the minutes:
TO_CHAR(date_column,'HH24MI')
For example:
select to_char(sysdate,'HH24MI') from dual;
TO_CHAR(SYSDATE,'HH24MI')
-------------------------
0331
Elapsed: 00:00:00.007
1 rows selected.
select to_char(systimestamp,'HH24MI') from dual;
TO_CHAR(SYSTIMESTAMP,'HH24MI')
------------------------------
0331
Elapsed: 00:00:00.006
1 rows selected.
Well, looking at what you posted, if values that column contains look exactly like that, then it is one of CHAR family datatypes because there's no TIME datatype in Oracle, as pmdba already told you. It would certainly help if you explained it properly, instead of letting us guess.
Anyway: if that's so and if values really are stored that way:
SQL> create table test as
2 select '01:00' col from dual union all
3 select '24:00' from dual union all
4 select '03:00' from dual;
Table created.
SQL> desc test
Name Null? Type
----------------------------------------- -------- ---------------------------
COL CHAR(5)
then you'd just have to remove the colon:
SQL> select col, replace(col, ':', '') result
2 from test;
COL RESULT
----- ----------
01:00 0100
24:00 2400
03:00 0300
SQL>
As I said: explain it properly.

How to compare date in string with sysdate in Oracle?

I am new with Oracle and still get used to SQL Server.
I do not understand on why the command below would return '1' when clearly sysdate which is today is 29-Apr-15 that clearly before 30-Apr-15
It should return 0. But I do not understand why it returns 1.
Any ideas? Thanks =)
SELECT CASE WHEN sysdate > to_date('30-Apr-15','DD-MON-YYYY') THEN '1' ELSE '0' END
FROM DUAL
you're missing the century from your date
SELECT CASE WHEN sysdate > to_date('30-Apr-2015','DD-MON-YYYY') THEN '1' ELSE '0' END
FROM DUAL
Because you have used 15 instead of 2015. You need to be aware of the Y2K bug. Using 'YY' format for year in a DATE is a bad idea. Always try to use 'YYYY' when converting a string into DATE
Or else, use the RR format to overcome the Y2K issue.
For example,
SQL> alter session set nls_date_format='mm/dd/yyyy';
Session altered.
SQL> SELECT TO_DATE('30-Apr-15','DD-MON-RR') RR,
2 TO_DATE('30-Apr-15','DD-MON-YYYY') YY
3 FROM DUAL;
RR YY
---------- ----------
04/30/2015 04/30/0015
SQL>
Using the same in your query:
SQL> SELECT
2 CASE
3 WHEN sysdate > to_date('30-Apr-15','DD-MON-RR')
4 THEN '1'
5 ELSE '0'
6 END
7 FROM DUAL
8 /
C
-
0
SQL>

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>

Resources