システム日付を連続的に変更する方法
システム日付をある固定値 にするにはオラクルの FIXED_DATE 初期化パラメータを使って設定することができる。
しかし、常に一定というのは特定のテストにおいてのみ有効であり、
やはり任意の日付で時が自動的に経過してくれる方が便利である。
システム日付を連続的に変更する例
システム日付を任意の日付から任意の進行具合で設定するには、以下のような非常に簡単なファンクションかスクリプトにより実現できる。
P_SECOND_RATE パラメータの値を変化させることで時間の進行度合いを自由に設定できる。
注意
- デフォルトの秒間隔は1秒であるがプログラムの処理時間は0ではないため長時間動作させていると誤差が発生する。
- FIX_DATE で有効なのは SYSDATE 関数のみで SYSTIMESTAMP 関数 など他の新しい関数には効果が無い。
CREATE OR REPLACE PROCEDURE RIVUS.PARALLEL_DATE(
P_START_WITH VARCHAR2, -- 開始日時
P_SECONDS POSITIVEN, -- 仮想側での適用する秒数
P_SECOND_RATE NUMBER := 1.0 -- 1 秒を何秒に換算するか (1.0 未満だと速く進む)
)
AUTHID CURRENT_USER
IS
vDate DATE;
vDateStr VARCHAR2(30);
vSecondRate NUMBER;
BEGIN
vDate := TO_DATE(P_START_WITH, 'YYYY-MM-DD HH24:MI:SS');
vSecondRate := ABS(NVL(P_SECOND_RATE,1));
FOR i in 0..P_SECONDS
LOOP
vDateStr := TO_CHAR(vDate, 'YYYY-MM-DD HH24:MI:SS');
EXECUTE IMMEDIATE
'ALTER SYSTEM SET FIXED_DATE=''' || vDateStr || ''' SCOPE=MEMORY';
DBMS_LOCK.SLEEP(vSecondRate);
vDate := vDate + INTERVAL '1' SECOND;
END LOOP;
EXECUTE IMMEDIATE 'ALTER SYSTEM SET FIXED_DATE=NONE SCOPE=MEMORY';
END;
/
実行例(プログラムの実行セッションは終了するまでプロンプトは戻らない)
-- ユーザー rivus に権限付与
SQL> grant execute on dbms_lock to rivus;
SQL> grant alter system to rivus;
-- 以上の権限を付与するか面倒なら SYSDBA で実行する。
-- 日付の書式は厳密でなくても動作する。
--
-- 1999-12-31 11:59:30 〜 2000-01-01 01:00:30
SQL> call rivus.parallel_date('1999/12/31 12:59:30', 60);
...
... 別セッションでテストプログラムを実行...
... 約 60 秒間に渡って懐かしの 2000年問題のテストが…
...
-- 約 61 秒経過するとシステム日付は現在の時刻に戻る。
関連事項