次の方法で共有


INSTEAD OF トリガの式と計算列

ビューの選択リストには、列名のみで構成される単純式以外の式を含めることができます。このビューの INSTEAD OF トリガは、INSERT や UPDATE に指定した値からベース テーブルの列に設定する必要がある値を正確に判断するロジックを備えている必要があります。たとえば、次のような式を設定できます。

  • 定数やある種の関数のように、どのテーブルのどの列にもマップされないビューの式
  • 2 つ以上の列の文字列を連結して形成される複合式など、複数の列にマップされるビューの式
  • 関数内の列を参照するなど、1 つのベース テーブルの列の値を変換するビューの式

ベース テーブルの計算列を参照する単純式のビュー列にも同じことが適用されます。計算列を定義する式には、ビューの選択リスト内の高度な複合式と同じ形式を指定できます。

ビューの選択リストには、次のような、どのベース テーブルの列にもマップされない式を含めることができます。

CREATE VIEW ExpressionView
AS
SELECT *, GETDATE() AS TodaysDate
FROM AdventureWorks.HumanResources.Employee

TodaysDate 列は、テーブルのどの列にもマップされませんが、SQL Server 2005 では、TodaysDate 列を inserted テーブルに作成し、ExpressionView に定義された INSTEAD OF トリガに渡す必要があります。ただし、inserted.TodaysDate 列は NULL 値を許容するので、ExpressionView を参照する INSERT ステートメントは、この列に値を指定する必要はありません。式がテーブルの列にマップされないため、このトリガはこの列の INSERT で指定されたすべての値を無視できます。

この方法を、他の列に依存しない結果を作成するベース テーブルの計算列を参照するビューの単純式に、次のように適用できます。

CREATE TABLE ComputedExample
   (
    PrimaryKey    int PRIMARY KEY,
    ComputedCol   AS SUSER_NAME()
   )

一部の複合式は、次のように、複数の列にマップされます。

CREATE TABLE SampleTable
     (
      PriKey    int,
      FirstName nvarchar(20),
      LastName  nvarchar(30)
     )
GO
CREATE VIEW ConcatView
AS
SELECT PriKey, FirstName + ' ' + LastName AS CombinedName
FROM SampleTable

ConcatView の式 CombinedName には、FirstName 値と LastName 値を連結した値が含まれます。INSTEAD OF INSERT トリガが ConcatView に定義されている場合は、INSERT ステートメントで CombinedName 列に値を指定する方法についての規則を設定し、そのトリガが FirstName 列に挿入する文字列の一部と LastName 列に挿入する文字列の一部を決定できるようにする必要があります。規則 'first_name;last_name' を使用して、INSERT ステートメントで CombinedName の値を指定するという規則を選択すると、次のように、このトリガは INSERT 処理に成功します。

CREATE TRIGGER InsteadSample on ConcatView
INSTEAD OF INSERT
AS
BEGIN

   INSERT INTO SampleTable
      SELECT PriKey,
         -- Pull out the first name string.
         SUBSTRING(
            CombinedName,
            1,
            (CHARINDEX(';', CombinedName) - 1)
            ),
         -- Pull out the last name string.
         SUBSTRING(
            CombinedName,
            (CHARINDEX(';', CombinedName) + 1),
            DATALENGTH(CombinedName) - (CHARINDEX(';', CombinedName) + 1)
            )
      FROM inserted
END

これと同様のロジックが、複合式を含む計算列を参照する単純式のビュー列の処理にも必要です。

ビューの式の中には、たとえば、数学的な演算を実行して、または関数へのパラメータとして列を使用して、ベース テーブルの列の値を変換できるものもあります。この場合、INSTEAD OF INSERT トリガでのロジックの使用方法には、次の 2 つがあります。

  • すべての INSERT ステートメントでベース テーブルに指定される基になる値を指定し、トリガのロジックによって、その値を inserted テーブルからベース テーブルに移動するという規則を作成します。

  • すべての INSERT ステートメントで、そのビューの SELECT が返すと予想される値を指定するという規則を作成します。ただし、この場合トリガのロジックは、操作を逆にする必要があります。次に例を示します。

    CREATE TABLE BaseTable
      (
       PrimaryKey   int PRIMARY KEY,
       ColumnB      int,
       ColumnC      decimal(19,3)
      )
    
    CREATE VIEW SquareView AS
    SELECT PrimaryKey, ColumnB,
           -- Square the value of ColumnC
           SQUARE(ColumnC) AS SquareC
    FROM BaseTable
    
    CREATE TRIGGER SquareTrigger ON SquareView
    INSTEAD OF INSERT
    AS
    BEGIN
      INSERT INTO BaseTable
         SELECT PrimaryKey, ColumnB,
                 -- Perform logical inverse of function in view.
                 SQRT(SquareC)
         FROM inserted
    END
    

加算や減算のような数学演算を使用する複合式などでは、対象のベース テーブルの列に正確な値を作成するためにトリガが使用する値を、ユーザーが指定できない場合があります。たとえば、ビューの選択リストに IntColA + IntColB AS AddedColumns という式が含まれているとします。inserted.AddedColumns の値が 10 の場合、どのような意味になるでしょうか。3 + 7、2 + 8、または 5 + 5 でしょうか。inserted.AddedColumns の値だけでは、IntColAIntColB がどの値なのかわかりません。

このような場合、トリガをコード化して、代替ソースの情報を使用し、ベース テーブルの列に設定する値を決めることができます。INSTEAD OF トリガを含むビューの場合は、ビューの選択リストに必要な情報を格納して、トリガによって変更されるベース テーブルの NULL 値を許容しないすべての列に値を作成できるようにする必要があります。すべてのデータを inserted テーブルから直接取得する必要はありません。場合によっては、inserted テーブルの値をキー値にして、トリガがそれを使用して他のベース テーブルから関連データを取得することができます。

参照

概念

INSTEAD OF トリガの使用

ヘルプおよび情報

SQL Server 2005 の参考資料の入手