トランザクション内でユニークなTIMESTAMP値を取得する試みの実践
「トランザクション内でユニークなTIMESTAMP値を取得する試み」をDB2 v9.5で実践してみる。
その際の考慮点は以下のとおり。
- GLOBAL TEMPORARY TABLEを作成するにはUSER TEMPORARY TABLESPACEが必要。
- GLOBAL TEMPORARY TABLEは必ず"SESSION"スキーマに作成される。
- 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, ?)')
どんな動きをするかを検証したいだけなのでこれでよしとするが、実際の開発とかでは使えないな…