「トランザクション内でユニークなTIMESTAMP値を取得する試み」内での誤解
だいぶ前に、トランザクション内でユニークなTIMESTAMP値を取得する試み - HHeLiBeXの日記 正道編でGlobal Temporary Tableを使ったアプローチを書いたが、SQL規格上でのGlobal Temporary Tableに関して誤った理解をしていたことが判明。*1
Global Temporary Tableは、あらかじめ
CREATE GLOBAL TEMPORARY TABLE SQL_TBL_UNIQUE_TIMESTAMP (UNIQ_TS TIMESTAMP) ON COMMIT DELETE ROWS
と定義しておくと、トランザクションのセッションが開始されたときにそのセッション専用のテーブルインスタンスが生成されるらしい。つまり、Global Temporary Tableの定義自体はオブジェクト指向言語におけるクラス定義をするのと同じということ。
ということで、以前に書いた定義を書き直すと、以下のような感じ。
あらかじめ、
CREATE GLOBAL TEMPORARY TABLE SQL_TBL_UNIQUE_TIMESTAMP (UNIQ_TS TIMESTAMP) ON COMMIT DELETE ROWS CREATE FUNCTION SQL_UNIQUE_TIMESTAMP() RETURNS TIMESTAMP LANGUAGE SQL NOT DETERMINISTIC MODIFIES SQL DATA BEGIN DECLARE Result TIMESTAMP; DECLARE Flag_NotFound INTEGER DEFAULT 0; DECLARE CONTINUE HANDLER FOR NOT FOUND SET Flag_NotFound = 1; SELECT UNIQ_TS INTO Result FROM SQL_TBL_UNIQUE_TIMESTAMP; IF Flag_NotFound = 1 THEN SET Result = CURRENT_TIMESTAMP; INSERT INTO SQL_TBL_UNIQUE_TIMESTAMP ( UNIQ_TS ) VALUES ( Result ); END IF; RETURN Result; END
を定義しておく。
以前と変わったのは、Global Temporary Table参照時に動的SQLを使用していないことと、初期化を関数の中でまとめてやってしまっている点。もちろん、セッション開始後にできるだけ早く初期化を行うことでトランザクション開始時刻にできるだけ近いタイムスタンプ値を使いたいということであれば、Global Temporary Tableの初期化だけは先にやるというのもあり。
で、
INSERT INTO TBL(ID, TS) VALUES(1, SQL_UNIQUE_TIMESTAMP()) INSERT INTO TBL(ID, TS) VALUES(2, SQL_UNIQUE_TIMESTAMP())
のように定義した関数を呼び出せば、セッション中でユニークなTIMESTAMP値が取得できる。