0

I tried to update a lot of rows in date format ('DD-MON-YY'). S

So, in cases such 22-FEB-99, I got 22th February 1999, instead of 22th February 2099.

Is there a way to specify the year in such cases?

3
  • I'm sure this is a duplicate, but in the meantime: read about RR in the docs. But use 4-digit years if you have a choice; and look at date literals as well. Do you have to deal with dates before 1950? (Your problem description is a bit confusing - I assume you mean you expected 1999, but actually got 2099...) Commented Nov 2, 2022 at 8:45
  • 1
    @AlexPoole It is possibly the other way round and that the OP has inserted/updated the date column as a string '22-FEB-99' and the default format model for implicit string-to-date conversion is DD-MON-RR and the 99 has been converted to 1999 rather than the OP's expectation of 2099 and they need to (1) not rely on implicit conversion and (2), if they are going to use a format model, use YY rather than RR to get the correct year. However, yes, the problem description is confusing and could be clarified with a detailed minimal reproducible example. Commented Nov 2, 2022 at 9:29
  • Yes, I read it as updating using to_date(..., 'DD-MON-YY')`, but you're probably right. Commented Nov 2, 2022 at 9:44

2 Answers 2

2

I tried to update a lot of rows in date format ('DD-MON-YY').

If you have a DATE column then that is a binary data type consisting of 7 bytes (representing century, year-of-century, month, day, hour, minute and second); it ALWAYS has those components and it is NEVER stored in any (human-readable) format.

What you probably mean is that your client application (SQL Developer) is displaying the dates in the format DD-MON-RR and it is not showing you the century or time components.


Is there a way to specify the year in such cases?

Rather than letting the client application apply a default format for displaying the date, you can apply an explicit format using TO_CHAR:

SELECT TO_CHAR(your_date_column, 'FMDDth Month YYYY', 'NLS_DATE_LANGUAGE=English')
         AS formatted_date
FROM   your_table;

Which, for the sample data:

CREATE TABLE your_table (your_date_column) AS
SELECT SYSDATE FROM DUAL UNION ALL
SELECT DATE '2022-01-01' FROM DUAL UNION ALL
SELECT DATE '1970-01-01' FROM DUAL;

Outputs:

FORMATTED_DATE
2nd November 2022
1st January 2022
1st January 1970

in cases such 22-FEB-99, I got 22th February 1999, instead of 22th February 2099.

If you get the value 22th February 1999 then that is because the date is stored as 1999 and not 2099. Note: that a DATE data type always has a century component so the query will display what is stored in the column.

You have probably inserted (or updated) the date as a string:

INSERT INTO your_table (your_date_column)
VALUES('22-FEB-99');

'22-02-99' is not a date data type, it is a string literal. Oracle has tried to be helpful and implicitly convert the date to a string using the NLS_DATE_FORMAT session parameter effectively converting the query to:

INSERT INTO your_table (your_date_column)
VALUES(
  TO_DATE(
    '22-FEB-99',
     (SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_DATE_FORMAT')
  )
);

However, your NLS_DATE_FORMAT session parameter is set to DD-MON-RR and the RR format model will convert 99 to 1999 and not 2099.

What you need to do is NEVER use implicit conversion from strings to dates; instead:

  • Use a date literal:

    INSERT INTO your_table(your_date_column) VALUES (DATE '2099-02-22');
    
  • Use a timestamp literal (which also allows you to specify the time):

    INSERT INTO your_table(your_date_column) VALUES (TIMESTAMP '2099-02-22 00:00:00');
    
  • Explicitly convert the string using TO_CHAR and the correct format model:

    INSERT INTO your_table(your_date_column)
    VALUES (TO_DATE('22-FEB-99', 'DD-MON-YY', 'NLS_DATE_LANGUAGE=English'));
    

fiddle


Fixing invalid data

If you have the data as 1999 and want 2099 then you will need to fix it:

UPDATE your_table
SET    your_date_column = your_date_column + INTERVAL '100' YEAR(3)
WHERE  your_date_column = DATE '1999-02-22';

or:

UPDATE your_table
SET    your_date_column = ADD_MONTHS(your_date_column, 1200)
WHERE  your_date_column = DATE '1999-02-22';

or:

UPDATE your_table
SET    your_date_column = DATE '2099-02-22'
WHERE  your_date_column = DATE '1999-02-22';
Sign up to request clarification or add additional context in comments.

Comments

0

2-digits year is evil (does Y2K ring a bell?). You should really use 4 digits for years. Meanwhile, see whether YY vs. RR format models do any difference in your case.

(you don't have to alter the session; my database uses different date format and language so I'm setting it now)

SQL> alter session set nls_date_format = 'dd.mm.yyyy';

Session altered.

SQL> alter session set nls_date_language = 'english';

Session altered.

Sample data and how yy/rr affect the result:

SQL> with test (col) as
  2    (select '22-FEB-99' from dual)
  3  select to_date(col, 'dd-mon-yy') val1,
  4         to_date(col, 'dd-mon-rr') val2
  5  from test;

VAL1       VAL2
---------- ----------
22.02.2099 22.02.1999

SQL>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.