HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

トランザクション内でユニークなTIMESTAMP値を取得する試みの実践

トランザクション内でユニークなTIMESTAMP値を取得する試み」をDB2 v9.5で実践してみる。
その際の考慮点は以下のとおり。

  1. GLOBAL TEMPORARY TABLEを作成するにはUSER TEMPORARY TABLESPACEが必要。
  2. GLOBAL TEMPORARY TABLEは必ず"SESSION"スキーマに作成される。
  3. MODIFIES SQL DATAな関数を定義できない。

最後の点が一番厄介なのだが、関数がだめであるため、OUTパラメータを持つプロシジャを使うしかない。しかし、通常のコンテキストで変数を宣言してプロシジャを呼び出し、変数の値を以降のクエリで使用する、ということができない。
そこで、さらに別のプロシジャを定義し、その中で一連の処理を行う。
まずプロシジャなどの定義。

CREATE USER TEMPORARY TABLESPACE SQL_TS_UNIQ_TS

CREATE PROCEDURE SQL_UNIQUE_TIMESTAMP(
 OUT ts TIMESTAMP)
   LANGUAGE SQL
   NOT DETERMINISTIC
   MODIFIES SQL DATA
   BEGIN
      DECLARE stmt CLOB;

      SET stmt = 'SET ? = (SELECT UNIQ_TS FROM SESSION.SQL_TBL_UNIQUE_TIMESTAMP)';
      PREPARE pstmt FROM stmt;
      EXECUTE pstmt INTO ts;
   END

CREATE PROCEDURE SQL_SET_UNIQUE_TIMESTAMP(
 IN stmt CLOB)
   LANGUAGE SQL
   NOT DETERMINISTIC
   MODIFIES SQL DATA
   BEGIN
      DECLARE ts TIMESTAMP;
      CALL SQL_UNIQUE_TIMESTAMP(ts);
      PREPARE pstmt FROM stmt;
      EXECUTE pstmt USING ts;
   END

そして、セッション開始時に

DECLARE GLOBAL TEMPORARY TABLE SQL_TBL_UNIQUE_TIMESTAMP (UNIQ_TS TIMESTAMP)
   ON COMMIT DELETE ROWS

INSERT INTO SESSION.SQL_TBL_UNIQUE_TIMESTAMP(UNIQ_TS) VALUES(CURRENT_TIMESTAMP)

準備ができたところで、クエリ実行。ただし、直接実行するのではなく、定義したプロシジャにクエリ文字列を渡す。

CALL SQL_SET_UNIQUE_TIMESTAMP(
   'INSERT INTO TBL(ID, TS) VALUES(1, ?)')

CALL SQL_SET_UNIQUE_TIMESTAMP(
   'INSERT INTO TBL(ID, TS) VALUES(2, ?)')

どんな動きをするかを検証したいだけなのでこれでよしとするが、実際の開発とかでは使えないな…