2013-01-18 24 views
6

同じテーブルの同じイベントで発生する2つのトリガ間のロックの問題を防ぐにはどうすればよいですか?同じテーブルの2つの異なる更新トリガ

私が作業しているDBにはすでに暗号化されている更新トリガが1つありますので、変更できません。新しいタスクを達成するために別の更新トリガーを作成しました。データベースで直接テストすると正しく動作しますが、フロントエンドアプリケーションで製品を更新すると失敗します。明らかに、私のトリガーをアクティブにしても、両方のトリガーは失敗します。私が受け取るメッセージは、「文書はすでに開いています。私はそれを増やします」というものです。

これはロックの問題ですか?

テーブル上に複数のトリガー(同じイベントの場合)があると、誰かが言うところのrelated questionがあります。任意の助けをいただければ幸いです

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 

CREATE TRIGGER [dbo].[tr_st_rep_update] 
ON [dbo].[st] 
AFTER UPDATE 
AS 
    BEGIN 
     SET NOCOUNT ON; 

     IF (update(ref) 
      OR update(design) 
      OR update(u_update) 
      OR update(u_ativo) 
      OR update(stock) 
      OR update(epv1) 
      OR update(epv2) 
      OR update(epv3) 
      OR update(peso) 
      OR update(u_catnv1) 
      OR update(u_catnv2) 
      OR update(u_catnv3) 
      OR update(u_dpromoi) 
      OR update(u_dpromof) 
      OR update(u_destaque)) 
     BEGIN 
      IF (SELECT count(*) 
       FROM Inserted 
         INNER JOIN Deleted 
         ON Inserted.ststamp = Deleted.ststamp 
       WHERE inserted.u_ativo = 1 
         OR (Deleted.u_ativo = 1 
          AND Inserted.u_ativo = 0)) > 0 
       BEGIN 
        INSERT INTO RepData 
           (id, 
           REF, 
           familia, 
           stock, 
           epv1, 
           epv2, 
           epv3, 
           peso, 
           u_accao, 
           imagem, 
           process) 
        SELECT Inserted.ststamp AS id, 
         Inserted.REF  AS REF, 
         Inserted.familia AS familia, 
         Inserted.stock AS stock, 
         Inserted.epv1 AS epv1, 
         Inserted.epv2 AS epv2, 
         Inserted.epv3 AS epv3, 
         Inserted.peso AS peso, 
         CASE 
          WHEN Deleted.u_ativo = 1 
           AND Inserted.u_ativo = 0 THEN 'd' 
          ELSE 'u' 
         END    AS u_accao, 
         Inserted.imagem AS imagem, 
         0    AS process 
        FROM Inserted 
         INNER JOIN Deleted 
          ON Deleted.ststamp = Inserted.ststamp 
        WHERE inserted.u_ativo = 1 
          OR (Deleted.u_ativo = 1 
           AND Inserted.u_ativo = 0) 
       END 
     END 
    END 

は、ここに私のトリガーコードです。

更新日:データベースはMSSQL 2008

+1

**正確**のエラーメッセージ(またはメッセージが英語でない場合は少なくともエラー番号)を表示できますか? 「ドキュメントは既に開いています。値を増やします」というSQL Serverエラーメッセージのようには聞こえません。 –

+0

私はそのメッセージ以外は得られません。エラーとして表示されることはなく、情報メッセージとして表示されます。関連している場合、操作は製品在庫の更新です。 – Fabio

+1

場合は、プロファイラを実行していない場合はどこに書かれている、そのアプリケーションのログを確認し、何が起こっているかを参照してください – WKordos

答えて

0

問題を解決しました。

私は実際にはテーブルのロックに関連するものだと思っていますが、このケースではInsertedテーブルに問題の原因が分かりません。

インサートされたステートメントの代わりにstテーブルから直接値を取得するように、内側のselectステートメントを変更しました。

ありがとうございました。

+1

ああ、OK。つまり、もう1つのトリガーが[st]表の行を変更していたことを意味します。これは[st]では反映されますが、[inserted]では反映されません。私の推測によれば、これは他の場所(おそらく[RepData]にある)でいくつかの重要な違反を引き起こしたということでしょう。 – RBarryYoung

8

トリガを使用して展開後のサイト内の開発とカスタマイズを行うことは魅力的ですが、まずは悪い考えであり、このような問題は継続的に発生します。

ただし、これを指定すると、最初のテーブルに複数のトリガーを持つことができますが、それは問題ではありません。

第2に、エラーメッセージ "ドキュメントはすでに開かれていますが、私はその値を増やします"は、クライアントアプリケーションまたは他の(暗号化された)トリガーのいずれかであり、SQL Serverエラーメッセージではありません。暗号化されたトリガーを最初に実行するように設定するか、トリガーを最後に実行するように設定することもできます。これはおそらく問題は解決しませんが、は、暗号化されたトリガーから、管理しやすい方法で報告および/またはアドレッシングする可能性の高いトリガーにエラーを移動します。

トリガーである可能性がある唯一の問題は、もう1つのトリガーがRepDataテーブルにも書き込み中で、重複したキー違反の原因となっている場合です。


トリガー順序は、here記載されsp_settriggerorderシステム・プロシージャを介して制御することができます。

+0

ニースの答えは、ありがとう! したがって、どのようにトリガーの実行順序を管理できますか? – Fabio

関連する問題