私は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)
何が悪いのですか?
「トリガーが他のユーザーを起動できるようにする」オプションは「真」を表示します。
ここに問題があります:
updateInvisibility
updateInvisibility
トリガーをトリガーしますそしてそれを続けているので、気付かないうちに一種の再帰的な方法で何度もトリガーをトリガーすることになります。 SQLサーバーは、この呼び出しのネストを32レベルの深さにできるようにし、次のエラーをスローします。
ストアドプロシージャ、関数、トリガー、またはビューのネストレベルが最大値を超えています(制限32)
それはかなり明確です。
コードのみのソリューションは、ネストレベルをチェックして、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 のコメントで指摘されているように、再帰的トリガーを無効にすることで、この問題を回避できます。