良い解決策はありません
データベースで空の日時値を処理する方法の問題には、適切な解決策がありません。
NULLを避けてください
クリス・デイト博士が「SQL標準のガイド」などで説明しているように、NULLは非常に悪夢です。一般的に、可能な限り避ける必要があります。SQLデータベースでは、これは各列を次のように宣言することを意味しますNOT NULL
(これをデフォルトにする方法があればいいのにと思います)。賢明な場合は、ある種のデフォルト値を設定します。
日時に適切なデフォルト値がない
ただし、日時値のデフォルト値を設定すると、非常に混乱する可能性があります。SQL標準もJDBC/java.sql。*も、特定の値を「空」のフラグとして定義していません。
Java 8以降に組み込まれているjava.timeフレームワークは、最小値と最大値を、、、、およびクラスの定数としてInstant
定義LocalDateTime
しLocalDate
ますLocalTime
。これらの値は、解決の重大な問題を除いて、フラグ値として機能する可能性があります。これらのjava.timeクラスはナノ秒に解決されますが、多くのデータベースはPostgresのマイクロ秒などのより大きな粒度を持っています。最小値と最大値は非常に極端であるため、より小さな粒度に切り捨てると、その意味が変わります。
ゼロ値
直感的に、ゼロ値の日時、 0000-00-00 00:00:00.0
//を検討すると考えるかもしれません。それほど単純ではありません。0000-00-00
00:00:00.0
ゼロ月/日なし
まず、の月00
や日などはありません00
。さて、0000-01-01
1月1日に変更できます。
ゼロ年なし
次号:そのような年はありません0000
。すべてのデータベースについてはわかりませんが、少なくともPostgresではそのようなゼロ年はありません。このような値を挿入しようとすると、エラーが発生します。
INSERT INTO moment_ -- TIMESTAMP WITH TIME ZONE.
VALUES ( '0000-01-01 00:00:00.0Z' ) ;
…エラーをスローします:
ERROR: date/time field value out of range: "0000-01-01 00:00:00.0Z"
LINE 2: VALUES ( '0000-01-01 00:00:00.0Z' ) ;
^
********** Error **********
0000
1年目に変更し0001
ます。
INSERT INTO moment_ -- TIMESTAMP WITH TIME ZONE.
VALUES ( '0001-01-01 00:00:00.0Z' ) ;
SET TIME ZONE 'UTC' ;
TABLE moment_ ;
0001-01-01 00:00:00 + 00
BC
その数は、対AD
時代の要点です。ADからBCに移動する動作を確認するために、1時間を減算してみましょう。ちなみに、などの文字列BC
はロケールに依存するため、状況によって異なる場合があります。また、この日時操作を正しく完了するには、タイムゾーンをUTCに設定する必要があることに注意してください。
SET TIME ZONE 'UTC' ;
INSERT INTO moment_ -- TIMESTAMP WITH TIME ZONE.
VALUES ( TIMESTAMP '0001-01-01 00:00:00.0Z' - INTERVAL '1 hour' ) ;
SET TIME ZONE 'UTC' ;
TABLE moment_ ;
結果は年0001 BC
なので、からにジャンプ0001
し0001 BC
ます。年ゼロはありません0000
。
"0001-12-31 23:00:00 + 00 BC"
したがって、特定のフラグ値を使用することにした場合、真のゼロ値を使用することはできませんが、1年目のADの1月1日であるゼロに近い値を使用することはできます。'0001-01-01 00:00:00.0Z'
タイムゾーン
この特別なフラグ値を使用する場合は、タイムゾーンに注意する必要があります。
文字列を渡すとき、SQLセッションの現在のデフォルトのタイムゾーンが暗黙的に適用されます(少なくともPostgresでは)。
NULLの並べ替え
私自身の仕事では、実際にほぼすべての列をNULLではなく、デフォルトを設定しています。ただし、実行可能なフラグ値がないため、日時列は例外です。そして、私はこれに苦しんでいます。具体的には、 SQL標準ではNULLのデフォルトのソート順が明示的に定義されていないNULLS FIRST
ため、 /NULLS LAST
修飾子の使用方法を難しい方法で学びました。