3

この最近の投稿により、私は Oracle でのユリウス日変換の調査に忙殺され、Oracle 11.1 のバグと思われるものに出くわしました。テストケースは次のとおりです。

ケース1。

SELECT TO_CHAR(TO_TIMESTAMP('0', 'J'), 'DD MON SYYYY') FROM DUAL

ここで定義されているように、これは「01 JAN -4713」を返すはずですが、代わりにエラーが発生します

ORA-01854: julian date must be between 1 and 5373484

ケース 2。

SELECT TO_CHAR(TO_TIMESTAMP('1', 'J'), 'DD MON SYYYY') FROM DUAL

これは、上記の拡張として "02 JAN -4713" を返す必要があります (ユリウス日より 1 日後) が、代わりに "01 JAN -4712" (1 年未満の日ずれ) を返します。

ケース 3。

SELECT TO_CHAR(TO_TIMESTAMP('1721424', 'J'), 'DD MON SYYYY') FROM DUAL

「01 JAN 0001」を返します。それはいいです(それが行く限り)。上記の日付値から 1 を減算すると、前日、つまり 31 DEC -0001 (ゼロ年は存在しません) が返されると予想されます。ただし、以下を実行すると

SELECT TO_CHAR(TO_TIMESTAMP('1721423', 'J'), 'DD MON SYYYY') FROM DUAL

次のエラーがスローされます。

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

オラクルがゼロの年を生成しようとしたことを示しています。

(上記のテストケースでは TO_TIMESTAMP が使用されていますが、TO_DATE を使用するとまったく同じ問題が発生することに注意してください)。

誰でも知っていますか

  1. これらの問題は Oracle によって文書化されていますか?
  2. これらの問題は 11.2 でもまだ存在しますか?

共有してお楽しみください。


以下の Phil の回答によると、これらの問題は 11.2 でも発生します。

クトゥルフのフタグン。


10.2.0.4 の同じバグ

4

3 に答える 3

2

オラクルが何をすべきかを知りたいときは、オラクルのドキュメント「ユリウス日は、紀元前 4712 年 1 月 1 日からの日数です」を参照してください。

その言い回しは、ユリウス 1 日が紀元前 4712 年 1 月 1 日、つまり 1 月 2 日から 1 日であることを暗示しているように見えます。しかし、ユリウス日付計算の現在の実装は長い間行われており、既存のコードは動作に依存しています。 . (Oracle に実装されている Julian の定義が変更された場合、私たちは困惑することになると思います。) この時点で、紀元前 4713 年 12 月 31 日からの日数はせいぜいドキュメントのバグです。

EDIT Call Interface Programmer's Guideで Julian 1 が 1 月 1 日の参照を見つけました。通常のデータベース プログラマーが目にすることのない場所です。

以下は、ウィキペディアとオラクルの年の違いを説明しています。

Oracle Databaseは、ユリウス日を計算する天文システムを使用します。このシステムでは、紀元前4713年が-4712として指定されます。対照的に、ユリウス日を計算する歴史的なシステムでは、紀元前 4713 年を -4713 と指定しています。オラクルのユリウス日を履歴システムを使用して計算された値と比較する場合は、紀元前の日付の 365 日の違いを考慮してください。詳細については、http://www.usno.navy.mil/USNO/astronomical-applications/astronomical-information-center/millennium を参照して ください

ケース3は私にとってニュースです。取り上げていただきありがとうございます。その動作をカバーする参考文献は知りません。関連している:

SQL> select to_date('0001-01-01', 'YYYY-MM-DD') 
    - to_date ('-0001-12-31', 'SYYYY-MM-DD') from dual;

TO_DATE('0001-01-01','YYYY-MM-DD')-TO_DATE('-0001-12-31','SYYYY-MM-DD')
-----------------------------------------------------------------------
                                                                    367

SQL> select months_between(to_date('0001-01-01', 'YYYY-MM-DD')
  2      , to_date ('-0001-12-31', 'SYYYY-MM-DD')) from dual;

MONTHS_BETWEEN(TO_DATE('0001-01-01','YYYY-MM-DD'),TO_DATE('-0001-12-31','SYYYY-MM-DD'))
---------------------------------------------------------------------------------------
                                                                             12.0322581

どうやら存在しない年 0 は閏年です。

于 2012-05-03T19:10:11.727 に答える
1

11.2.0.1.0 で実行された同じクエリを次に示します。

PHIL@PHILL11G2 > select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE    11.2.0.1.0  Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production

Elapsed: 00:00:00.04
PHIL@PHILL11G2 > SELECT TO_CHAR(TO_TIMESTAMP('0', 'J'), 'DD MON SYYYY') FROM DUAL;
SELECT TO_CHAR(TO_TIMESTAMP('0', 'J'), 'DD MON SYYYY') FROM DUAL
                            *
ERROR at line 1:
ORA-01854: julian date must be between 1 and 5373484


Elapsed: 00:00:00.00
PHIL@PHILL11G2 > SELECT TO_CHAR(TO_TIMESTAMP('1', 'J'), 'DD MON SYYYY') FROM DUAL;

TO_CHAR(TO_T
------------
01 JAN -4712

Elapsed: 00:00:00.00
PHIL@PHILL11G2 > SELECT TO_CHAR(TO_TIMESTAMP('1721424', 'J'), 'DD MON SYYYY') FROM DUAL;

TO_CHAR(TO_T
------------
01 JAN  0001

Elapsed: 00:00:00.00
PHIL@PHILL11G2 > SELECT TO_CHAR(TO_TIMESTAMP('1721423', 'J'), 'DD MON SYYYY') FROM DUAL;
SELECT TO_CHAR(TO_TIMESTAMP('1721423', 'J'), 'DD MON SYYYY') FROM DUAL
                            *
ERROR at line 1:
ORA-01841: (full) year must be between -4713 and +9999, and not be 0


Elapsed: 00:00:00.04
PHIL@PHILL11G2 > 
于 2012-05-03T12:58:50.040 に答える