日付関数に関する検証 外伝 その1
<日付関数に関する検証 外伝>
ペンネーム: ダーリン
【SYSTIMESTAMPとCURRENT_TIMESTAMPの怪 その1】
大変ご無沙汰しております。久々登場のダーリンです。
今回は日付関数のちょっと変わった動きについてお話させていただきます。
Oracle 9i 以降、秒未満の時刻を表示できる日付時刻に関する関数が増えてい
ることはすでにご存知かと思います。
従来から存在する SYSDATE 関数とあわせるとこれらは以下の 5つの関数です。
SYSDATE DATE型 SYSTIMESTAMP TIMESTAMP WITH TIMEZONE型 CURRENT_DATE DATE型 CURRENT_TIMESTAMP TIMESTAMP WITH TIMEZONE型 LOCAL_TIMESTAMP TIMESTAMP型
すでに気がついている方もいるかと思いますが、 実は上記の関数のなかであ
る組み合わせの関数を実行すると、、、ちがう値を取得してきます。
タイムゾーンの設定による違いではありません。
タイムゾーンについてはこちら
(http://www.atmarkit.co.jp/fdb/rensai/sqlclinic04/sqlclinic04_3.html)を
参照してみてください。
ここでいう異なる値とは、ミリ秒(1/1000秒)以下のずれのことです。
以下はその実例です。
SQL> select SYSDATE,SYSTIMESTAMP,CURRENT_TIMESTAMP,LOCALTIMETAMP from dual; SYSDATE SYSTIMESTAMP CURRENT_TIMESTAMP -------- ------------------------------- ------------------------------- 06-11-20 06-11-20 21:40:40.978854 +09:00 06-11-20 21:40:40.978898 +09:00 LOCALTIMESTAMP ------------------------ 06-11-20 21:40:40.978898
SYSTIMESTAMP と、 CURRENT_TIMESTAMP および LOCALTIMESTAMP の時刻が数十
マイクロ秒のレベルでずれていますね。
多くの方は上記の SQL では暗黙的に同じ値が取得されることを期待している
のではないでしょうか?
日付関数を並べるなんてナンセンスと思われるかもしれませんが、これらの日
付関数では取得される TIMEZONE が異なるため、TIMEZONE を意識する場合は
便利な使い方です。
これらの関数について、マニュアルにはおおよそ以下のように記載されていま
す。
SYSDATE このファンクションはローカル・データベースの 日時を戻します。 SYSTIMESTAMP データベースが存在するシステムの タイムゾーン (小数部を含む)を戻します。 CURRENT_DATE セッション・タイムゾーンの現在の日付を DATE データ型のグレゴリオ暦の値で戻します。 CURRENT_TIMESTAMP セッション・タイムゾーンの現在の日付および 時刻をTIMESTAMP WITH TIME ZONE データ型の値 で戻します。 LOCALTIMESTAMP セッションのタイムゾーンの現在の日付および 時刻をTIMESTAMPデータ型の値で戻します。
つまり SYSDATE 関数と SYSTIMESTAMP 関数はローカルデータベース、あるい
は、システムの日時データを戻しているのに対し、それ以外の関数はセッショ
ンタイムゾーンを考慮した日時を戻しているようです。
日時データのデータソースが異なるか、あるいは、同一データに対して変換を
かけて値を取得しているのでしょうか。
Oracle がそもそもどうやって日付時刻の情報を取得しているのか気になります。
こんなときどうすればこのような情報を得ることができるでしょうか?
何か尻尾ぐらいはつかめないでしょうか。 というわけで、今回はトレースを
とることにします。
まず、psコマンドでトレースを取得するプロセスを見つけます。
トレースする対象のセッションは専用接続で接続し、 そのプロセスを特定する
ほうがわかりやすくておすすめです。
今回はLinux上でトレースを取得するので、strace コマンドを使ってみます。
□■ 対象セッションのプロセス特定 $ ps -elf | grep oracle | grep test1 | grep beq 000 S oracle 15690 1 1 77 0 - 60699 pipe_w 21:40 ? 00:00:00 oracletest1 (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq))) □■ 対象セッションのトレース $ strace -p 15690 Process 15690 attached - interrupt to quit read(8,
strace コマンドの 第2引数はトレースするPIDです。
これで準備完了です。では対象のセッションで日付を取得してみましょう。
まずはSYSDATEです。
SQL> select SYSDATE from dual; SYSDATE