「トランザクション内でユニークな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, ?)')
どんな動きをするかを検証したいだけなのでこれでよしとするが、実際の開発とかでは使えないな…