Ora 01841 ошибка

Коллеги-разработчики с радостью сообщили, что наконец-то сломали 12-й Oracle обнаружили проблему, а Александр Шакура подготовил отличный тесткейс:

12.1.0.2@ SQL> create table partit_Tab tablespace users
  2  PARALLEL ( DEGREE 16 INSTANCES 1 ) PARTITION BY RANGE(DT) INTERVAL(NUMTOYMINTERVAL(1, 'MONTH'))
  3  ( PARTITION p0 VALUES LESS THAN (TO_DATE('01-01-2005', 'DD-MM-YYYY')))
  4  as
  5  select sysdate dt from dual
  6  union all
  7  select sysdate-300 dt from dual
  8  union all
  9  select sysdate+300 dt from dual
 10  /
 
Table created
 
SQL> select * from partit_Tab ch
  2   where ch.dt < to_date('01-SEP-15','DD-MON-YY')
  3      or ch.dt between to_date('01-SEP-15','DD-MON-YY') and to_date('30-SEP-15','DD-MON-YY')
  4  /
 
DT
-----------
03.01.2015
 
SQL> select * from partit_Tab ch
  2   where ch.dt < date '2015-09-01'
  3      or ch.dt between date '2015-09-01' and date '2015-09-30'
  4  /
 
select * from partit_Tab ch
 where ch.dt < date '2015-09-01'
    or ch.dt between date '2015-09-01' and date '2015-09-30'
 
ORA-01841: (full) year must be between -4713 and +9999, and not be 0

В процессе обследования выяснилось, что:

1) ORA-01841 возникает только для 4-х значных форматов года (YYYY), включая Date Literal вида date’2015-09-01′
2) Explain Plan возвращает ту же ошибку, при этом трейс оптимизатора драматически обрывается на преобразовании Table Expansion (TE):

Query transformations (QT)
**************************
JF: Checking validity of join factorization for query block SEL$1 (#0)
JF: Bypassed: not a UNION or UNION-ALL query block.
ST: not valid since star transformation parameter is FALSE
TE: Checking validity of table expansion for query block SEL$1 (#0)
implied predicates generated: "CH"."START_DT"<TO_DATE('2015-09-01','yyyy-mm-dd') OR "CH"."START_DT">=TO_DATE('2015-09-01','yyyy-mm-dd') AND "CH"."START_DT"<=TO_DATE('2015-09-30','yyyy-mm-dd')

, а запрос при отключении этого преобразования select /*+ NO_EXPAND_TABLE(ch) */ … работает без ошибок

3) проблема характерна именно для 12.1.0.2, в предыдущих версиях оптимизатора проблем не обнаружено:

SQL> select/*+ optimizer_features_enable('12.1.0.1') */ * from partit_Tab ch
  2   where ch.dt < date '2015-09-01'
  3      or ch.dt between date '2015-09-01' and date '2015-09-30'
  4  /
 
DT
-----------
03.01.2015

С помощью тех.поддержки удалось найти свежее улучшение, оформленное в виде фикса:

SQL> @fix 14558315
 
   BUGNO VALUE SQL_FEATURE                DESCRIPTION                                             OPTIMIZER_FEATURE_ENABLE
-------- ----- -------------------------- ------------------------------------------------------- ------------------------
14558315     1 QKSFM_CARDINALITY_16615686 table expansion support for interval partitioned tables 12.1.0.2

, отключение которого на уровне системы, сессии или запроса устраняет проблему

Bug 14558315 (TABLE EXPANSION DOES NOT WORK WITH INTERVAL PARTITIONING) я уже упоминал в
Особенности преобразования Table Expansion, и с помощью кейса из этой заметки легко проверить, что баг 14558315 действительно уже исправлен в 12.1.0.2:

12.1.0.2.@ SQL> alter session set "_fix_control"='14558315:on'; -- включен (по умолчанию)

Session altered.

SQL> select/*+ expand_table(t)*/ * from t where x = 10; -- подсказка форсирует TE несмотря на Cost

         X          Y
---------- ----------
        10          1

1 row selected.

SQL> SELECT * FROM TABLE(dbms_xplan.display_cursor('','',format => '+outline'));

PLAN_TABLE_OUTPUT
-------------------------------------------------
SQL_ID  81uwwbx7xp974, child number 0
-------------------------------------
select/*+ expand_table(t)*/ * from t where x = 10

Plan hash value: 3514974290

------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                    | Name    | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                             |         |       |       |   122 (100)|          |       |       |
|   1 |  VIEW                                        | VW_TE_1 |     3 |    78 |   122   (3)| 00:00:01 |       |       |
|   2 |   UNION-ALL                                  |         |       |       |            |          |       |       |
|   3 |    PARTITION RANGE SINGLE                    |         |     1 |     8 |     2   (0)| 00:00:01 |     1 |     1 |
|*  4 |     TABLE ACCESS BY LOCAL INDEX ROWID BATCHED| T       |     1 |     8 |     2   (0)| 00:00:01 |     1 |     1 |
|*  5 |      INDEX RANGE SCAN                        | T_I     |     1 |       |     1   (0)| 00:00:01 |     1 |     1 |
|   6 |    PARTITION RANGE SINGLE                    |         |     1 |     8 |    41   (3)| 00:00:01 |     2 |     2 |
|*  7 |     TABLE ACCESS FULL                        | T       |     1 |     8 |    41   (3)| 00:00:01 |     2 |     2 |
|   8 |    PARTITION RANGE INLIST                    |         |     1 |     8 |    79   (3)| 00:00:01 |       |       |
|*  9 |     TABLE ACCESS FULL                        | T       |     1 |     8 |    79   (3)| 00:00:01 |       |       |
------------------------------------------------------------------------------------------------------------------------

Outline Data
-------------

  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('12.1.0.2')
      DB_VERSION('12.1.0.2')
      OPT_PARAM('optimizer_index_caching' 10)
      ALL_ROWS
      ...
      EXPAND_TABLE(@"SEL$1" "T"@"SEL$1")      -- TE работает, см.план
      ...
      END_OUTLINE_DATA
  */

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - filter("T"."Y"<2)
   5 - access("X"=10)
   7 - filter(("X"=10 AND "T"."Y">=2 AND "T"."Y"<3))
   9 - filter("X"=10)


SQL> alter session set "_fix_control"='14558315:off'; -- fix_control выключен

Session altered.

SQL> select/*+ expand_table(t)*/ * from t where x = 10;

         X          Y
---------- ----------
        10          1

1 row selected.

SQL> SELECT * FROM TABLE(dbms_xplan.display_cursor('','',format => '+outline'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------
SQL_ID  81uwwbx7xp974, child number 1
-------------------------------------
select/*+ expand_table(t)*/ * from t where x = 10

Plan hash value: 3557914527

--------------------------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |       |       |    79 (100)|          |       |       | -- TE не работает
|   1 |  PARTITION RANGE ALL|      |     1 |     8 |    79   (3)| 00:00:01 |     1 |1048575|
|*  2 |   TABLE ACCESS FULL | T    |     1 |     8 |    79   (3)| 00:00:01 |     1 |1048575|
--------------------------------------------------------------------------------------------

Outline Data
-------------

  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('12.1.0.2')
      DB_VERSION('12.1.0.2')
      OPT_PARAM('optimizer_index_caching' 10)
      OPT_PARAM('_fix_control' '14558315:0')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      FULL(@"SEL$1" "T"@"SEL$1")
      END_OUTLINE_DATA
  */

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("X"=10)

Из описания бага до сих пор следует, что исправление планируется в 12.2, Bugs fixed in each 12.1.0.2 Patch Set Update также не упоминает баг 14558315, разгадываем загадки с support-ом

UPD Bug 21606703 : ORA-1841 SELECTING FROM INTERVAL-PARTITIONED TABLE
Base Bug 21467081 INCONSISTENT RESULTS WHEN NOT USING TO_DATE FUNCTION

I do have this value SQL Query. But facing the error (as the title).

BETWEEN TO_DATE('20190401', 'yyyymmdd') AND TO_DATE('20190501', 'yyyymmdd')

ORA-01841: (full) year must be between -4713 and +9999, and not be 0

  • sql
  • oracle

asked Jun 18, 2019 at 6:34

Jeannell Casaje's user avatar

5

  • can you post the full sql? There is nothing wrong with this fragment — select * from dual where sysdate BETWEEN TO_DATE('20190401', 'yyyymmdd') AND TO_DATE('20190501', 'yyyymmdd') works just fine (dbfiddle.uk/… — see no error). The error is elsewhere in your sql

    Jun 18, 2019 at 6:37

  • share full condition and what is the data type of comparison column

    Jun 18, 2019 at 6:37

  • the 20190401/20190501 is coming as TEXT/String.

    Jun 18, 2019 at 6:39

  • @JeannellCasaje convert your string column date type then do comparison

    Jun 18, 2019 at 6:42

  • What data type is the column you are trying to compare?

    – user330315

    Jun 18, 2019 at 7:40

Load 7 more related questions

Show fewer related questions

TO_DATE(TO_CHAR(datevalue, 'DD/MM/YYYY'),'DD/MM/YYYY') is removing any time component which is effectively the same as: TRUNC( datevalue ).

Then TO_DATE(SYSDATE , 'DD/MM/YYYY') is probably where your error lies as TO_DATE( stringvalue, format_model ) takes a string as the first argument so you are effectively doing:

TO_DATE(
  TO_CHAR(
    SYSDATE,
    ( SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_DATE_FORMAT' )
  ),
  'DD/MM/YYYY'
)

It doesn’t make sense as SYSDATE is already of the DATE data type so you don’t need to use TO_DATE with it.

Finally, TO_CHAR(SYSDATE - datevalue)*-1 Why are you converting it to a string then multiplying it by a number when you can just do:

(SYSDATE - datevalue)*-1

But you don’t even need the *-1 as you can just swap the terms around:

(datevalue - SYSDATE)

Tidying it all up you want something like:

SELECT  MYTABLE." ID ", 
        NVL(
          MAX( TRUNC( ADD_MONTHS(MYTABLE." XISSU_DT " ,MYTABLE." XTNR ") ) ),
          SYSDATE
        ) MAXLASTINSDATE,
        SYSDATE, 
        ( NVL(
            MAX( TRUNC( ADD_MONTHS(MYTABLE." XISSU_DT " ,MYTABLE." XTNR ") ) ),
            SYSDATE
          )
          - SYSDATE
        ) AS MaturityPeriod
FROM   MYTABLE
where  MYTABLE." STATUS " = 'A'
group by MYTABLE." ID "

April 28, 2021

I got ” ORA-01841: (full) year must be between -4713 and +9999, and not be 0 ” error in Oracle.

ORA-01841: (full) year must be between -4713 and +9999, and not be 0

Details of error are as follows.

ORA-01841: (full) year must be between -4713 and +9999, and not be 0
 
Cause: Illegal year entered  

Action: Input year in the specified range


(full) year must be between -4713 and +9999, and not be 0

This ORA-01841 errors are related with the illegal year entered.

To solve this error, Full year in your date should be must be between -4713 and +9999, and not be 0

Do you want to learn Oracle Database for Beginners, then read the following articles.

Oracle Tutorial | Oracle Database Tutorials for Beginners ( Junior Oracle DBA )

About Mehmet Salih Deveci

I am Founder of SysDBASoft IT and IT Tutorial and Certified Expert about Oracle & SQL Server database, Goldengate, Exadata Machine, Oracle Database Appliance administrator with 10+years experience.I have OCA, OCP, OCE RAC Expert Certificates I have worked 100+ Banking, Insurance, Finance, Telco and etc. clients as a Consultant, Insource or Outsource.I have done 200+ Operations in this clients such as Exadata Installation & PoC & Migration & Upgrade, Oracle & SQL Server Database Upgrade, Oracle RAC Installation, SQL Server AlwaysOn Installation, Database Migration, Disaster Recovery, Backup Restore, Performance Tuning, Periodic Healthchecks.I have done 2000+ Table replication with Goldengate or SQL Server Replication tool for DWH Databases in many clients.If you need Oracle DBA, SQL Server DBA, APPS DBA,  Exadata, Goldengate, EBS Consultancy and Training you can send my email adress [email protected].-                                                                                                                                                                                                                                                 -Oracle DBA, SQL Server DBA, APPS DBA,  Exadata, Goldengate, EBS ve linux Danışmanlık ve Eğitim için  [email protected] a mail atabilirsiniz.

I have been working on a query and couldn’t figure out the solution for this error. Hope can get insights from the community on how to solve this:

select TO_TIMESTAMP(to_char(RTC_TIMESTAMP, 'yyyy-mm-dd hh24:mi:ss') || ',' || lpad(rtc_event_order_seq, 3, '0'), 'YYYY-MM-DD HH24:MI:SS,FF3') AS TIME_STAMP,
TO_TIMESTAMP(to_char((Lead(RTC_TIMESTAMP,1)over(order by RTC_TIMESTAMP)), 'yyyy-mm-dd hh24:mi:ss') || ',' || lpad(rtc_event_order_seq, 3, '0'), 'YYYY-MM-DD HH24:MI:SS,FF3') AS NEXT_TIMESTAMP
from mytable

the Error I have been getting is:

ora-01841 full year must be between 4713 and 9999 and not be 0

>Solution :

The problem is with the final row in the result set, when there is no lead row to get values from. Lead(RTC_TIMESTAMP,1)over(order by RTC_TIMESTAMP) returns null, you concatenate a comma and milliseconds value. The next_timestamp calculation ends up as:

TO_TIMESTAMP(',001', 'YYYY-MM-DD HH24:MI:SS,FF3')

which is what throws that error. You can see that if you run the query without the to_timestamp() calls.

The value is probably wrong anyway – presumably you should be looking at the lead rtc_event_order_seq as well – which would also be null, by trying to convert ',' would also fail.

You can wrap the next_timestamp is a case expression to avoid the issue:

select TO_TIMESTAMP(to_char(RTC_TIMESTAMP, 'yyyy-mm-dd hh24:mi:ss') || ',' || lpad(rtc_event_order_seq, 3, '0'), 'YYYY-MM-DD HH24:MI:SS,FF3') AS TIME_STAMP,
  case when Lead(RTC_TIMESTAMP,1)over(order by RTC_TIMESTAMP) is not null then
    TO_TIMESTAMP(to_char((Lead(RTC_TIMESTAMP,1)over(order by RTC_TIMESTAMP)), 'yyyy-mm-dd hh24:mi:ss')
      || ',' || lpad(Lead(rtc_event_order_seq,1)over(order by RTC_TIMESTAMP), 3, '0'), 'YYYY-MM-DD HH24:MI:SS,FF3')
    end AS NEXT_TIMESTAMP
from mytable
TIME_STAMP NEXT_TIMESTAMP
01-JAN-22 12.13.14.002000000 01-JAN-22 12.13.14.001000000
01-JAN-22 12.13.14.001000000 null

But rather than converting to and from strings, you can add multiples of one millisecond directly:

select RTC_TIMESTAMP + (rtc_event_order_seq * interval '0.001' second) AS TIME_STAMP,
  case when Lead(RTC_TIMESTAMP, 1) over (order by RTC_TIMESTAMP) is not null then
    Lead(RTC_TIMESTAMP, 1) over (order by RTC_TIMESTAMP)
      + (Lead(rtc_event_order_seq, 1) over (order by RTC_TIMESTAMP) * interval '0.001' second)
    end AS NEXT_TIMESTAMP
from mytable
TIME_STAMP NEXT_TIMESTAMP
01-JAN-22 12.13.14.002000000 01-JAN-22 12.13.14.001000000
01-JAN-22 12.13.14.001000000 null

fiddle

Понравилась статья? Поделить с друзьями:
  • Ora 01804 ошибка
  • Ora 01779 ошибка
  • Ora 01691 ошибка как исправить
  • Ora 01536 ошибка
  • Ora 01461 ошибка