7

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

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

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

テーブルに (同じイベントに対して) 複数のトリガーを設定できると誰かが言う関連する質問があります。

これが私のトリガーコードです:

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 です

4

2 に答える 2

15

トリガーを使用して、デプロイ後のサイト内開発とカスタマイズを行うことは魅力的ですが、最初は悪い考えであり、このような問題が継続的に発生することは間違いありません.

ただし、これを考えると、 First: テーブルには複数のトリガーを含めることができますが、それは問題ではありません

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

オフハンドではありますが、トリガーから発生する可能性がある唯一の問題は、他のトリガーもRepDataテーブルに書き込みを行っており、二重書き込みが重複キー違反を引き起こしている場合です。


トリガーの順序は、ここsp_settriggerorderに記載されているシステム プロシージャによって制御できます。

于 2013-01-18T20:30:59.277 に答える
1

問題が解決しました。

問題の原因は本当にわかりませんが、テーブルのロックに関連していると思いますが、この場合は挿入されたテーブルにあります。

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

みんな、ありがとう。

于 2013-01-18T19:43:59.150 に答える