DB2 9.5 で SQLプロシージャ(2)

前回は例外処理がよくわからんというところまででしたが、例外処理、一応入れてみました。これでたぶん大丈夫そう。大丈夫だと思う。おそらく。。うん。

hoge1
CREATE PROCEDURE hoge01
(
   IN  ic_DOC_ID                VARCHAR(16)
  ,OUT oi_SQLCODE               INT
  ,OUT oc_SQLSTATE              CHAR(5)
  ,OUT ov_MESSAGE_TEXT          VARCHAR(70)
)
  SPECIFIC hoge01
  LANGUAGE SQL
  DETERMINISTIC
  NO EXTERNAL ACTION
  MODIFIES SQL DATA
BEGIN
  /*--------------------------------------------------------*/
  /*  変数の宣言                                            */
  /*--------------------------------------------------------*/
  DECLARE vtemp           CHAR(10);
  DECLARE SQLCODE         INT         DEFAULT 0;            --SQLCODE (0:データが戻された,100:データが戻されない)
  DECLARE SQLSTATE        CHAR(5)     DEFAULT '00000';      --SQLSTATE
  DECLARE vi_SQLCODE      INT         DEFAULT 0;            --SQLCODE (0:データが戻された,100:データが戻されない)
  DECLARE vc_SQLSTATE     CHAR(5)     DEFAULT '00000';      --SQLSTATE
  DECLARE vv_MESSAGE_TEXT VARCHAR(70) DEFAULT 'NORMAL END'; --MESSAGE_TEXT
  
  DECLARE oc_DOC_ID        CHAR(16)  DEFAULT ' ';
  
  -- 条件ハンドラー用
  DECLARE vi_NOT_FOUND INT DEFAULT 0;
  /*--------------------------------------------------------*/
  /*  カーソルの宣言                                        */
  /*--------------------------------------------------------*/
  /*--------------------------------------------------------*/
  /*  条件ハンドラーの宣言                                  */
  /*--------------------------------------------------------*/
  DECLARE CONTINUE HANDLER FOR NOT FOUND --SQLSTATE='02000'アンサーセット無し
  BEGIN
    SET vi_NOT_FOUND = 1;
  END;
  
  DECLARE CONTINUE HANDLER FOR SQLWARNING --SQLSTATE='01***'
  BEGIN
  END;
  
  DECLARE EXIT HANDLER FOR SQLEXCEPTION --SQLSTATE='01***','02***'以外全部
  BEGIN
    SET vtemp       = SQLSTATE || CAST(SQLCODE AS CHAR(5));
    SET oc_SQLSTATE = SUBSTR(vtemp,1,5);
    SET oi_SQLCODE  = INT(SUBSTR(vtemp,6,5));
    GET DIAGNOSTICS EXCEPTION 1 vv_MESSAGE_TEXT = MESSAGE_TEXT;
    
    
    IF vv_MESSAGE_TEXT IS NULL
    THEN
      CASE vc_SQLSTATE
        WHEN '21000' THEN  --スカラー全選択、SELECT INTOの結果が複数行になった
          SET ov_MESSAGE_TEXT = 'hoge01:TOO MANY ROWS' || ' : ' || vc_DOCUMENT_ID;
          
        WHEN '42704' THEN  --未定義の名前
          SET ov_MESSAGE_TEXT = 'hoge01:UNDEFINED NAME' || ' : ' || vc_DOCUMENT_ID;
          
        WHEN '22012' THEN  --ゼロ除算
          SET ov_MESSAGE_TEXT = 'hoge01:DIVISION BY ZERO' || ' : ' || vc_DOCUMENT_ID;
          
        WHEN '23505' THEN  --ユニーク制約違反
          SET ov_MESSAGE_TEXT = 'hoge01:VIOLATION FOR UNIQUE CONSTRAINT' || ' : ' || vc_DOCUMENT_ID;
          
        WHEN '23502' THEN  --NULL制約違反
          SET ov_MESSAGE_TEXT = 'hoge01:VIOLATION FOR NOT NULL CONSTRAINT' || ' : ' || vc_DOCUMENT_ID;
          
        ELSE
          SET ov_MESSAGE_TEXT = 'hoge01:OTHERS EXCEPTION' || ' : ' || vc_DOCUMENT_ID;
          
      END CASE;
    ELSE
      SET ov_MESSAGE_TEXT = vv_MESSAGE_TEXT || ' : ' || vc_DOCUMENT_ID;
    END IF;
  
    -- ログ出力
    CALL LOG_hoge(
            'hoge1'
           ,oi_SQLCODE
           ,oc_SQLSTATE
           ,ov_MESSAGE_TEXT
         );
    
  END;
  
  /*--------------------------------------------------------*/
  /*  ステートメント                                        */
  /*--------------------------------------------------------*/
  SET oc_DOC_ID = ic_DOC_ID;
  
  DELETE FROM XXX
   WHERE DOC_ID = ic_DOC_ID
  ;
  
  INSERT INTO
     XXX
  VALUES (
     oc_DOC_ID, ..
  )
  ;
  
  COMMIT;
  
END
@

上の中で LOG_hoge を CALL しているが、なぜかというと、どうも、DB2 SQLプロシージャは、ファイルシステムにファイル出力が出来ないみたいだから。
Oracleならば、UTL_FILE使えるのに。。。かなりショック!9.7からは使えるのかもしれないが、それまでの人たちはどうしたらいいのか?ログ出力のために、CやJavaでストアドプロシージャを書けというのか?用意されていない事がお粗末にしか思えなくなってきた。

さて、LOG_hogeの方はというと、まず、テーブルとシーケンスを準備しておく。

シーケンスの作成
CREATE SEQUENCE SCHEMA_NAME.LOG_hoge_SEQ
 AS INTEGER
 START WITH 1
 INCREMENT BY 1
 CYCLE;
ログテーブルの作成
CREATE TABLE SCHEMA_NAME.LOG_hoge_TABLE (
  LOG_NO               INT       NOT NULL ,
  CRT_TIME_STAMP       TIMESTAMP NOT NULL ,
  PGID                 CHAR(15)  NOT NULL ,
  SQLCODE              INT,
  SQLSTATE             CHAR(5),
  MESSAGE_TEXT         VARCHAR(70)
)
 IN "USERSPACE1" ;
LOG_hoge
CREATE PROCEDURE LOG_hoge
(
   IN  ic_PGID                  VARCHAR(15)
  ,IN  ii_SQLCODE               INT
  ,IN  ic_SQLSTATE              CHAR(5)
  ,IN  iv_MESSAGE_TEXT          VARCHAR(70)
)
  SPECIFIC LOG_hoge
  LANGUAGE SQL
  DETERMINISTIC
  NO EXTERNAL ACTION
  MODIFIES SQL DATA
BEGIN
  /*--------------------------------------------------------*/
  /*  変数の宣言                                            */
  /*--------------------------------------------------------*/
  DECLARE vtemp           CHAR(10);
  DECLARE SQLCODE         INT         DEFAULT 0;            --SQLCODE (0:データが戻された,100:データが戻されない)
  DECLARE SQLSTATE        CHAR(5)     DEFAULT '00000';      --SQLSTATE
  DECLARE vi_SQLCODE      INT         DEFAULT 0;            --SQLCODE (0:データが戻された,100:データが戻されない)
  DECLARE vc_SQLSTATE     CHAR(5)     DEFAULT '00000';      --SQLSTATE
  DECLARE vv_MESSAGE_TEXT VARCHAR(70) DEFAULT 'NORMAL END'; --MESSAGE_TEXT
  
  /*--------------------------------------------------------*/
  /*  カーソルの宣言                                        */
  /*--------------------------------------------------------*/
  /*--------------------------------------------------------*/
  /*  条件ハンドラーの宣言                                  */
  /*--------------------------------------------------------*/
  DECLARE CONTINUE HANDLER FOR NOT FOUND --SQLSTATE='02000'アンサーセット無し
  BEGIN
  END;
  
  DECLARE CONTINUE HANDLER FOR SQLWARNING --SQLSTATE='01***'
  BEGIN
  END;
  
  DECLARE EXIT HANDLER FOR SQLEXCEPTION --SQLSTATE='01***','02***'以外全部
  BEGIN
    SET vtemp       = SQLSTATE || CAST(SQLCODE AS CHAR(5));
    SET vc_SQLSTATE = SUBSTR(vtemp,1,5);
    SET vi_SQLCODE  = INT(SUBSTR(vtemp,6,5));
    GET DIAGNOSTICS EXCEPTION 1 vv_MESSAGE_TEXT = MESSAGE_TEXT;
  END;
  
  /*--------------------------------------------------------*/
  /*  ステートメント                                        */
  /*--------------------------------------------------------*/
  --■ ログテーブルに情報を書き出す
  INSERT INTO LOG_hoge_TABLE
    VALUES (
       NEXT VALUE FOR LOG_hoge_SEQ --ログNO
      ,CURRENT_TIMESTAMP           --作成タイムスタンプ
      ,ic_PGID                     --PGID
      ,ii_SQLCODE                  --SQLCODE
      ,ic_SQLSTATE                 --SQLSTATE
      ,iv_MESSAGE_TEXT             --MESSAGE_TEXT
    );
  
  --■ コミットする。
  COMMIT;
  
END
@

今日はここまで。