プロが教えるわが家の防犯対策術!

Oracle8iのストアドプロシジャを作成しています。
SELECT SYSDATE で取得したシステム時間から任意時間前の時刻を算出し、CHAR(16)の文字列(YYYYMMDDHHMMSSMS)にしたいのですが、
うまくいきません。

次のようなやり方をしています。
(1)システム時刻を取得し、CHAR型変数へ格納。
(2)時、分、秒ごとにCHAR型の変数へセット。
(3)TO_NUMBER関数でNUMBER型へ変換して、NUMBER型変数に格納。
(4)任意時間前の時刻の算出。

SQLPLUSの標準出力にログを出して確認したところ、分や秒(W_CHECK_SS )がマイナスになってしまいます。
どのようにすればうまくいくのかアドバイスをいただけたらと思います。

今は以下のように書いています。
CREATE OR REPLACE PROCEDURE TESTSP (
IN_KIJUN_TIMEINNUMBER--監視基準時間(秒)
)
IS
W_CURRENT_TIME16CHAR(16);--システム時刻(16桁)
W_CURRENT_TIME14CHAR(14);--システム時刻(14桁)
W_CURRENT_YYYYMMDDCHAR(8);--システム時刻(YYYYMMDD)
W_CURRENT_HHNUMBER(2);--システム時刻(HH)
W_CURRENT_MMNUMBER(2);--システム時刻(MM)
W_CURRENT_SSNUMBER(2);--システム時刻(SS)
W_CURRENT_HH_STRCHAR(2);--システム時刻(HH)CHAR型
W_CURRENT_MM_STRCHAR(2);--システム時刻(MM)CHAR型
W_CURRENT_SS_STRCHAR(2);--システム時刻(SS)CHAR型
W_CHECK_SECNUMBER(5);--基準前時刻(計算用)
W_CHECK_HHNUMBER(2);--基準前時刻(HH)
W_CHECK_MMNUMBER(2);--基準前時刻(MM)
W_CHECK_SSNUMBER(2);--基準前時刻(SS)
W_CHECK_HMSCHAR(16);--基準前時刻(16桁)
BEGIN
/*-- システム時刻の取得 --*/
SELECT TO_CHAR(SYSDATE, 'YYYYMMDDHH24MISS') INTO W_CURRENT_TIME14 FROM DUAL;
-- ◆DEBUG START
DBMS_OUTPUT.PUT_LINE('・システム時刻14 = ' || W_CURRENT_TIME14);
-- ◆DEBUG END
/*-- 基準前時刻の計算 --*/
W_CURRENT_YYYYMMDD := SUBSTR(W_CURRENT_TIME14,1,8);
W_CURRENT_HH_STR := SUBSTR(W_CURRENT_TIME14,9,2);
W_CURRENT_MM_STR := SUBSTR(W_CURRENT_TIME14,11,2);
W_CURRENT_SS_STR := SUBSTR(W_CURRENT_TIME14,13,2);

W_CURRENT_HH := TO_NUMBER(W_CURRENT_HH_STR);
W_CURRENT_MM := TO_NUMBER(W_CURRENT_MM_STR);
W_CURRENT_SS := TO_NUMBER(W_CURRENT_SS_STR);
--
W_CHECK_SEC := W_CURRENT_HH * 3600
+ W_CURRENT_MM * 60
+ W_CURRENT_SS
- IN_KIJUN_TIME;

W_CHECK_HH := W_CHECK_SEC / 3600;
W_CHECK_SEC := W_CHECK_SEC - (W_CHECK_HH * 3600);
W_CHECK_MM := W_CHECK_SEC / 60;
W_CHECK_SS := W_CHECK_SEC - (W_CHECK_MM * 60);
W_CHECK_HMS := W_CURRENT_YYYYMMDD || W_CHECK_HH || W_CHECK_MM || W_CHECK_SS || '00';
-- ◆DEBUG START
DBMS_OUTPUT.PUT_LINE('・W_CHECK_HH = ' || W_CHECK_HH);
DBMS_OUTPUT.PUT_LINE('・W_CHECK_MM = ' || W_CHECK_MM);
DBMS_OUTPUT.PUT_LINE('・W_CHECK_SS = ' || W_CHECK_SS);
-- ◆DEBUG END
(以下省略)


【標準出力】
SQL> EXEC TESTSP(60);
・引数:監視基準時間(秒) = 60
・システム時刻14 = 20070308222543
・システム時刻(YYYYMMDD) = 20070308
・W_CHECK_HH = 22
・W_CHECK_MM = 25
・W_CHECK_SS = -17

※システム時刻[22:25:43]の60秒前は22:24:43なので、
[2007030822244300]という文字列を作成したいのです

A 回答 (3件)

#2です。


こんな感じでどうでしょう?

create or replace procedure testsp(in_kijun_time in number)
is
wkday_dt date;
wk_day_c varchar2(20);
day_hh char(2);
day_mi char(2);
day_ss char(2);
begin
wkday_dt := sysdate;
dbms_output.put_line('現在時刻:'||to_char(wkday_dt,'yyyymmddhh24miss')||'00');
wkday_dt := wkday_dt+(in_kijun_time/(24*60*60));

dbms_output.put_line('算出時刻:'||to_char(wkday_dt,'yyyymmddhh24miss')||'00');

-- パーツ単位で取得したいのなら
day_hh := to_char(wkday_dt,'hh');
day_mi := to_char(wkday_dt,'mi');
day_ss := to_char(wkday_dt,'ss');

dbms_output.put_line('時:'||day_hh);
dbms_output.put_line('分:'||day_mi);
dbms_output.put_line('秒:'||day_ss);
end;
    • good
    • 0
この回答へのお礼

教えていただいた方法でできました。とてもシンプルなスクリプトになりました。
ありがとうございました。

お礼日時:2007/03/09 16:31

単純に指定された秒後の日付を取得したいのであれば日付型で計算すればよいのではないのでしょうか?



select sysdate+(60/(24*60*60)) nextdate from dual
で60秒後の日付になるので後はTO_CHARで編集してあげれば良いと思います。

やりたいことと違っていたらごめんなさい。
    • good
    • 0
この回答へのお礼

SQLで計算してあげれば簡単にできるのですね。
SQLをもっと勉強します。
ありがとうございます。

お礼日時:2007/03/09 15:37

W_CHECK_MM := W_CHECK_SEC / 60;


のところで、24.71... → 25 に四捨五入されてしまっているのではないでしょうか。
    • good
    • 0
この回答へのお礼

確かに四捨五入されています。
だからマイナスになっていたのですね。
ご指摘ありがとうございます。

お礼日時:2007/03/09 15:35

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!