0

I'm trying to convert the column DATA_EMISSAO which has a char format but contains all dates for the Table (it only contains dates).

The problem is: the way information was loaded into Oracle let the row set with different patterns as shown below:

enter image description here

As you can see there are 2 patterns: 'DD/MM/YYYY' and Excel's Date number format.

1) First I tried to convert them with the code:

  select distinct to_char(DATA_EMISSAO, 'DD-MM-YYYY') from MASTERSAF;

But got the error:

  ORA-01722: invalid number
  01722. 00000 -  "invalid number"
  *Cause:    The specified number was invalid.
  *Action:   Specify a valid number.

2) Then I tried the following:

  select distinct to_char(to_date(DATA_EMISSAO, 'DD-MM-YYYY'), 'DD-MM-YYYY') from MASTERSAF;

But got no success...

   ORA-01847: day of month must be between 1 and last day of month
   01847. 00000 -  "day of month must be between 1 and last day of month"
   *Cause:    
   *Action:  

Do you think it should be better to construct a condition to read each row condition and apply the proper "transformation"?

Also, I don't know why, but if I run

   select to_char(to_date(DATA_EMISSAO, 'DD/MM/YYYY') + 0, 'DD/MM/YYYY') as DATES2 from MASTERSAF;

It seems to go fine, but if I put a distinct before,

                select distinct to_char(to_date(DATA_EMISSAO, 'DD/MM/YYYY') + 0, 'DD/MM/YYYY') as DATES2 from MASTERSAF;

I get the following error:

    ORA-01847: day of month must be between 1 and last day of month
    01847. 00000 -  "day of month must be between 1 and last day of month"
    *Cause:    
    *Action:

Do you have an idea to correct the dates? (unfortunately I cannot change on excel because the database is too large....)

MT0
  • 143,790
  • 11
  • 59
  • 117
Petter_M
  • 435
  • 3
  • 10
  • 20

1 Answers1

1

Use a CASE statement to match the different formats and convert them each to a date using the appropriate method (DD/MM/YYYY can be converted using TO_DATE and a single number can be converted by adding days to 1900-01-01):

Oracle Setup:

CREATE TABLE dates ( date_emissao ) AS
SELECT '12/08/2016' FROM DUAL UNION ALL
SELECT '42716' FROM DUAL

Query:

SELECT CASE
       WHEN REGEXP_LIKE( date_emissao, '^\d+$' )
       THEN DATE '1900-01-01' + TO_NUMBER( date_emissao )
       ELSE TO_DATE( date_emissao, 'DD/MM/YYYY' )
       END AS date_emissao
FROM   dates;

Output:

| DATE_EMISSAO |
| :----------- |
| 2016-08-12   |
| 2016-12-14   |

db<>fiddle here

MT0
  • 143,790
  • 11
  • 59
  • 117
  • thank you very much! By the way, why I cannot put a "select distinct" on the result? I tried `select distinct DATE_EMISSAO from [**the code you indicated**]` but got the error `ORA-01843: not a valid month`. – Petter_M Jan 24 '19 at 21:48
  • @Petter_Mendes [db<>fiddle.uk](https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=78557d9d205eaff7f7a44244df295dfb) Just add the `DISTINCT` keyword straight after the `SELECT` and before the first column. – MT0 Jan 24 '19 at 21:57
  • Yes, I did the following: `SELECT DISTINCT DATE_EMISSAO FROM (SELECT CASE WHEN REGEXP_LIKE(DATE_EMISSAO, '^\d+$') THEN DATE '19000-01-01' TO_NUMBER(DATE_EMISSAO) ELSE TO_DATE(DATE_EMISSAO, 'DD/MM/YYYY') END AS DATA_EMISSAO FROM MASTERSAF)`; And After running it I got the following error: `ORA-00936: missing expression 00936. 00000 - "missing expression" *Cause: *Action: Error at Line: 2 Column: 3`. – Petter_M Jan 28 '19 at 20:00
  • If I put directly in the code `SELECT DISTINCT CASE WHEN REGEXP_LIKE(DATE_EMISSAO, '^\d+$') THEN DATE '19000-01-01' TO_NUMBER(DATE_EMISSAO) ELSE TO_DATE(DATE_EMISSAO, 'DD/MM/YYYY') END AS DATA_EMISSAO FROM MASTERSAF` I get the error: `ORA-01843: not a valid month 01843. 00000 - "not a valid month" *Cause: *Action:` – Petter_M Jan 28 '19 at 20:03
  • @Petter_Mendes `1900` only has 2 zeroes and you are missing the `+` symbol after the date literal. – MT0 Jan 28 '19 at 20:50
  • yes, sorry for the typos in the post but the code I ran was correct. Sorry for my dummy question. So, the code should be **I)** `SELECT DISTINCT CASE WHEN REGEXP_LIKE( DATA_EMISSAO, '^\d+$' ) THEN DATE '1900-01-01' + TO_NUMBER( DATA_EMISSAO ) ELSE TO_DATE( DATA_EMISSAO, 'DD/MM/YYYY' ) END AS DATA_EMISSAO FROM MASTERSAF;` – Petter_M Jan 29 '19 at 15:59
  • or **II)** `SELECT DISTINCT DATA_EMISSAO (SELECT DISTINCT CASE WHEN REGEXP_LIKE( DATA_EMISSAO, '^\d+$' ) THEN DATE '1900-01-01' + TO_NUMBER( DATA_EMISSAO ) ELSE TO_DATE( DATA_EMISSAO, 'DD/MM/YYYY' ) END AS DATA_EMISSAO FROM MASTERSAF);` but as I mentioned the error persisted either way. – Petter_M Jan 29 '19 at 16:00