web-dev-qa-db-ja.com

Oracle:タイムスタンプを日付としてキャストし、結果を比較する

cast(timestamp as date)が何をしているのか本当にわかりません。 Oracle Database 11g Express Editionリリース11.2.0.2.0を使用しています。

_select cast(to_timestamp('20190516 08:00:00', 'yyyymmdd HH24:MI:SS') as date) from dual
_

セッションで使用している日付形式で日付20190516(時刻なし)を表示します。

_select to_timestamp('20190516 08:00:00', 'yyyymmdd HH24:MI:SS') from dual;
_

セッション形式で日付と時刻を表示します。これまでのところ、私が期待したすべてのもの。

だからキャスティングは時間部分を削除するようです。次に、キャストの結果を、SQL Serverでは機能するがOracleでは機能しない日付と比較したいと思います。

_select case when cast(to_timestamp('20190516 08:00:00', 'yyyymmdd HH24:MI:SS') as date) = to_date('20190516', 'yyyymmdd') then 1 else 0 end as match from dual; -- 0 = not matched
select case when trunc(to_timestamp('20190516 08:00:00', 'yyyymmdd HH24:MI:SS')) = to_date('20190516', 'yyyymmdd') then 1 else 0 end as match from dual; -- 1 = matched
_

最初の選択で示された日付だけではないように見える場合、cast(to_timestamp('20190516 08:00:00', 'yyyymmdd HH24:MI:SS') as date)によって正確に何が返されますか?結果を比較できないのはなぜですか?

示されているように、幸運にもtrunc()を使用した別の解決策があります。比較が機能しない理由と、castで比較を実行する可能性があるかどうかを知りたいのですが。私はSQL ServerからOracleにビューを移植しており、できるだけ同じにしたいと考えています。SQLServerではcastを使用してそれを行っています。

2
bugybunny

DATEからTIMESTAMPデータ型へのキャストは小数秒のみを削除するため、直接のto_date('20190516', 'yyyymmdd')比較は正しく失敗します。それはあなたを混乱させた単なるディスプレイの問題です。

Oracle DATEデータ型の定義( here から):

有効な日付範囲は、紀元前4712年1月1日から西暦9999年12月31日までです。デフォルトの形式は、NLS_DATE_FORMATパラメータによって明示的に、またはNLS_TERRITORYパラメータによって暗黙的に決定されます。サイズは7バイトに固定されています。このデータ型には、YEAR、MONTH、DAY、HOUR、MINUTE、およびSECONDの日時フィールドが含まれています。小数秒やタイムゾーンはありません。

このDB Fiddleデモ

これらのクエリはおそらく最もよく示しています:

-- cast to date, and format with TO_CHAR to show that the time element still exists
select  TO_CHAR(
               cast(to_timestamp('20190516 08:00:00', 'yyyymmdd HH24:MI:SS') as date)
                ,'yyyymmdd HH24:MI:SS') from dual; 

-- demonstrate that the fractional element gets removed 
select cast(
         cast(to_timestamp('20190516 08:00:00.123', 'yyyymmdd HH24:MI:SS.FF')
              as date) 
       as timestamp) from dual;
2
Philᵀᴹ