GETDATE()のような、実行のたびに結果が変化する関数は使えないという謎の仕様になっています。
システム日付を使いたい場合は、関数の外側で求めて、それをパラメータとして関数に引き渡して中で使う・・・というやり方がセオリーなんですが、既存の関数のインターフェースを絶対に変えたくないし、仕様変更等で内部でシステム日付使いたい・・・みたいな時には、結構困るかも。
そこで、ちょっと無理やりなのですが、32bit限定で、関数の中で使える、システム日付を求める関数を作ってみました。
この関数を、自分で作った関数の中から呼び出せばOKです。
やり方は、OLEオートメーションプロシージャを使って、スクリプトエンジンを呼び出し、JScriptで記述したシステム日付取得関数を間接的に呼び出してしまう・・・というものなんです。
32bit限定というのは、呼び出しているスクリプトエンジンが64bit対応してないんですね。
ちなみに、手のひらタブレットの東芝dynabook tab VT484で作りました。
SQL-Server 2014 EXPRESS(32bit版)なんですが、SQL-Server 2000でも使えます。
コードは以下のようになります。
CREATE FUNCTION F_GETDATE() RETURNS DATETIME AS BEGIN DECLARE @oOLEAP INT, --OLEオートメーションインスタンス化用 @iHR INT, --OLEオートメーションプロシージャ実行結果 @sRES VARCHAR(8000), --文字列型の結果格納エリア @dtRES DATETIME, --日付型結果格納エリア @sJS VARCHAR(8000) --JScript格納エリア ; --スクリプトエンジンのインスタンス化 EXEC @iHR= sp_OACreate 'MSScriptControl.ScriptControl',@oOLEAP OUT; IF @iHR <> 0 BEGIN RETURN CAST(0 AS DATETIME); END; --言語の決定 EXEC @iHR= sp_OASetProperty @oOLEAP,'Language','JScript'; IF @iHR <> 0 BEGIN RETURN CAST(0 AS DATETIME); END; --初期化 EXEC @iHR= sp_OAMethod @oOLEAP,'Reset' IF @iHR<>0 BEGIN RETURN CAST(0 AS DATETIME); END; --JScriptで日付取得関数作成 SET @sJS = 'function JS_GETDATE()' + '{' + 'var oDATE = new Date();' + 'var sDATE = "";' + 'sDATE += new String(oDATE.getFullYear()) + "-"; ' + 'sDATE += new String(oDATE.getMonth()+1) + "-"; ' + 'sDATE += new String(oDATE.getDate()) + " "; ' + 'sDATE += new String(oDATE.getHours()) + ":"; ' + 'sDATE += new String(oDATE.getMinutes()) + ":"; ' + 'sDATE += new String(oDATE.getSeconds()) + "."; ' + 'sDATE += new String(oDATE.getMilliseconds()); ' + 'oDATE = null; ' + 'return sDATE; ' + '}'; --JScriptで作った関数をメソッド登録 EXEC @iHR= sp_OAMethod @oOLEAP,'AddCode',NULL,@sJS; if @iHR<>0 BEGIN RETURN CAST(0 AS DATETIME); END; --JScript関数を実行して戻り値を文字列で取得 EXEC @iHR= sp_OAMethod @oOLEAP,'Run',@sRES OUT,'JS_GETDATE'; IF @iHR<>0 BEGIN RETURN CAST(0 AS DATETIME); END; --日付型に変換 SET @dtRES = CAST(@sRES AS DATETIME); --メモリ解放 EXEC @iHR= sp_OADestroy @oOLEAP; if @iHR<>0 BEGIN RETURN CAST(0 AS DATETIME); END; --結果の返却 RETURN @dtRES; END
ちなみに、OLEオートメーションプロシージャは、最初は使えなくなっているかも知れません。 その場合は以下で使用可能になります。
sp_configure 'show advanced options', 1; GO RECONFIGURE; GO sp_configure 'Ole Automation Procedures', 1; GO RECONFIGURE; GO
実行結果は以下の通りです。
GETDATE()と同じように動作し、自作関数からも動作します。
ただ、OLEオートメーションプロシージャって、どうなんだろう。
作っておいて今更ですが、業務システムとかで安易に使うと、リソースデッドロックとか、パフォーマンスの低下とか、色々問題が起きるかも知れないんで怖いかなぁと。
個人用途とかなら良いかも知れない。
ただ、OLEオートメーションプロシージャを使うと、確かに色々な事が出来るようになるので便利ではありますね。