web-dev-qa-db-ja.com

列を更新するT-SQLトリガー

私は2、3週間SQLクエリを使用しており、自分の過ちから学び理解しようとしています。私は2つの列IsInvisible (bit)ShortName (string)を持つテーブルを持っています。一方を変更してもう一方を更新すると、次のようになります。-ShortNameの前に〜を追加してIsInvisibleを1に、〜を削除して0に設定した場合-IsInvisibleを1に設定して、ShortNameの前に〜を追加し、0に設定して削除した場合。

私は次のようなことを試しました:

ALTER TRIGGER [dbo].[updateInvisibility]
ON [dbo].[table]
AFTER UPDATE
AS
BEGIN

UPDATE t
SET IsInvisible = (CASE WHEN i.ShortName like '~%' THEN 1 ELSE 0 END),
    ShortName = (CASE WHEN i.IsInvisible = 1 AND t.ShortName NOT LIKE '~%'
                 THEN '~' + t.ShortName
                 ELSE t.ShortName
            END)
FROM table t JOIN
     inserted i
     ON t.Id = i.Id;

end

私の問題は、列の一方または両方を更新しているときに何も起こらず、このエラーが発生することです。

Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32)

何が悪いのですか?

「トリガーが他のユーザーを起動できるようにする」オプションは「真」を表示します。

7
Dana

ここに問題があります:

  1. テーブルを更新します
  2. 更新トリガーをトリガーします:updateInvisibility
  3. トリガーでテーブルをもう一度更新して、updateInvisibilityトリガーをトリガーします

そしてそれを続けているので、気付かないうちに一種の再帰的な方法で何度もトリガーをトリガーすることになります。 SQLサーバーは、この呼び出しのネストを32レベルの深さにできるようにし、次のエラーをスローします。

ストアドプロシージャ、関数、トリガー、またはビューのネストレベルが最大値を超えています(制限32)

それはかなり明確です。

T-SQLソリューション

コードのみのソリューションは、ネストレベルをチェックして、1より大きい場合はそのままにします(1は更新によって最初に呼び出されます)。

IF TRIGGER_NESTLEVEL() > 1 RETURN;

このような:

ALTER TRIGGER [dbo].[updateInvisibility]
ON [dbo].[table]
AFTER UPDATE
AS
BEGIN
    IF TRIGGER_NESTLEVEL() > 1 RETURN;

    -- Do your work...
END

オルタナティブ

RBarryYoung のコメントで指摘されているように、再帰的トリガーを無効にすることで、この問題を回避できます。

10
CodingYoshi