SQL-Serverのストアド・ファンクションではUPDATEなどが実行できない
当然といえばそうなのかもしれませんが、SQL-Serverのストアド・ファンクションではUPDATEなどが実行できない。
TRY・・・CATCHも記述できないようです。関数は戻り値のみを返すもので、テーブル等に変更を与えてはいけないのでしょう。
さて、取敢えずストアド・ファンクションの簡単な例を示します。
前回使用したテストテーブルを利用して、ストアド・ファンクションを作成します。テーブルの構造は以下の感じです。
■スカラ値関数
テストテーブルAを利用した簡単な値を返すストアド・関数です。
与えられた検索用IDでテーブルAの「DATA1」カラムの内容を返す簡単な関数です。 SELECT文での実行は以下のようにします。
======================================
SELECT [dbo].[FuncTest2](1)
======================================
■テーブル値関数その1(インラインテーブル値)
テストテーブルAを利用した簡単な値を返すストアド・関数です。
SELECT文のFROM句で実行しますので、以下のようになります。
======================================
SELECT * FROM [dbo].[FuncTest3](1)
======================================
■テーブル値関数その2(複数の行を返すテーブル値)
テストテーブルAを利用した複数の行を返すストアド・関数です。
指定されたID以降のデータを全て返す様な動作を行います。
RETURNS句で指定されたTABLEにINSERTしていくことで、結果をテーブルの値として返します。
INSERTで追加してやればいろんなことができると思います。上の例ではコメント行になっていますが、 強制的にID「0」を作成することも可能です。
この関数の実行も「テーブル値関数その1」で行った方法と同様です。
■スカラ値関数にUPDATE文を記述
SQL実行結果として以下のエラーメッセージが表示されます。
============================================================
メッセージ 443、レベル 16、状態 15、プロシージャ FuncTest2、行 8
副作用のある演算子または時間に依存する演算子を関数内の 'UPDATE' で使用することはできません。
============================================================
TRY、CATCHを入れてもエラーが表示され使用出来ないようです。
SQL実行結果として以下のエラーメッセージが表示されます。
============================================================
メッセージ 443、レベル 16、状態 14、プロシージャ FuncTest2、行 6
副作用のある演算子または時間に依存する演算子を関数内の 'BEGIN TRY' で使用することはできません。
メッセージ 443、レベル 16、状態 14、プロシージャ FuncTest2、行 9
副作用のある演算子または時間に依存する演算子を関数内の 'END TRY' で使用することはできません。
メッセージ 443、レベル 16、状態 14、プロシージャ FuncTest2、行 10
副作用のある演算子または時間に依存する演算子を関数内の 'BEGIN CATCH' で使用することはできません。
メッセージ 443、レベル 16、状態 14、プロシージャ FuncTest2、行 11
副作用のある演算子または時間に依存する演算子を関数内の 'END CATCH' で使用することはできません。
============================================================
副作用のある処理をファンクションのなかでは記述できないので、 どうしても処理したいのであれば、ストアド・プロシージャとして作成するしかないようです。
そこで、結果として何かを返したいのであれば、引数に出力属性のものを持つしかありません。
また、プロシージャの中からファンクションを実行することはできますが、ファンクションの中から プロシージャを実行することはできないようです。
ファンクションのコールが入れ子になっていて、深いところでUPDATEなどを行いたい場合、 全てのファンクションをプロシージャにしないといけなくなってきます。
このあたりは、ファンクション、プロシージャの切り分けをしっかりしておく必要がありそうです。
■関連記事
⇒VB.NET:ADO.NETを使用したSQL-ServerのテーブルのCSV出力
⇒BCPコマンドでUnicode文字形式を使用したデータのインポート及びエクスポート(SQL Server)について
⇒ADO.NET での DataReader の入れ子エラー
⇒ADO.NET を使用した SQL-Server へのアクセス・クラス
⇒SQL-Serverの自動採番(IDENTITY値)の取得・リセット
⇒SQL-Serverのユーティリティ(BCPコマンド)を利用したテーブルへのインポート・エキスポート
⇒SQL-Serverのプロシージャ生成のバッチ実行
⇒SQL-Serverの関数・プロシージャのVB.NETでの実行
コメント