2

挿入されるデータに基づいて別のテーブルの情報を更新するように設計された挿入/更新トリガーを作成しました。トリガーが最後に実行する (または実行することになっている) ことは、トリガーの挿入部分で変更された可能性のある条件を持つターゲット テーブルからすべてのデータを削除することです。

DELETE最終ステートメントを除いて、すべてがトリガーで機能しているように見えます。ステートメントを実行してDELETEいますが、where 句のどの条件にも従っていません。テーブル内のすべてを削除するだけです。

NOT INwhere 句の を に変更してみましたがIN、それでも同じです。ステートメントを分離しDELETE、トリガーの外側でテストしたところ、正常に動作しました (同じ変数とサブクエリを使用)。

トリガーの動作で何か不足していますか?

コードは次のとおりです。

ALTER TRIGGER [dbo].[cust_trgr_profile_attribute] 
ON [dbo].[port_module_instance_setting]      
AFTER INSERT, UPDATE
AS

DECLARE @ModuleId INT=449,
        @MatchGroupModSetting VARCHAR(50) = 'AttributeGroup',
        @FilterGroupModSetting VARCHAR(50) = 'FilterAttributeGroup',
        @MatchAttributes TABLE (attribute_id INT),
        @FilterAttributes TABLE (attribute_id INT)

INSERT INTO @MatchAttributes
  SELECT DISTINCT camatch.attribute_id 
  FROM inserted I
  JOIN core_attribute camatch ON I.value = CONVERT(VARCHAR(10), camatch.attribute_group_id)
  JOIN port_module_instance pmi ON I.module_instance_id = pmi.module_instance_id
       AND pmi.module_id=@ModuleId
  WHERE I.name like @MatchGroupModSetting+'_'

INSERT INTO @FilterAttributes
  SELECT DISTINCT cafilter.attribute_id 
  FROM inserted I
  JOIN core_attribute cafilter ON I.value = CONVERT(VARCHAR(10), cafilter.attribute_group_id)
  JOIN port_module_instance pmi ON I.module_instance_id = pmi.module_instance_id
       AND pmi.module_id=@ModuleId
  WHERE I.name=@FilterGroupModSetting

IF ((SELECT COUNT(*) FROM @MatchAttributes) > 0 OR (SELECT COUNT(*) FROM @FilterAttributes) > 0)
BEGIN
    IF (SELECT COUNT(*) FROM @MatchAttributes) > 0
    BEGIN
        UPDATE cpa 
           SET cpa.[required]=0
          FROM cust_profile_attribute cpa
          JOIN @MatchAttributes ma ON cpa.attribute_id = ma.attribute_id
    END

    IF (SELECT COUNT(*) FROM @FilterAttributes) > 0
    BEGIN
        UPDATE cpa 
           SET cpa.[required]=0
          FROM cust_profile_attribute cpa
          JOIN @FilterAttributes fa ON cpa.attribute_id=fa.attribute_id
    END

    DELETE FROM cust_profile_attribute
    WHERE attribute_id NOT IN (SELECT distinct ca.attribute_id 
                               FROM core_attribute ca
                               JOIN port_module_instance_setting inst ON CONVERT(VARCHAR(10),ca.attribute_group_id) = inst.value
                               JOIN port_module_instance modinst ON inst.module_instance_id = modinst.module_instance_id
                                    AND modinst.module_id = @ModuleId
                               WHERE inst.name like @MatchGroupModSetting + '_'
                               OR inst.name like @FilterGroupModSetting)
END
4

1 に答える 1

0

トリガーがどのように機能するかについての私の基本的なロジックに欠陥があることを発見しました。私は今、何が起こっているのかについての理解を深め、他の人が助けるためにより多くの情報を明確に表現できるようになりました. 元の投稿を完全に変更しようとするよりも、新しい情報をここに投稿する方がよいと考えました。

基本的な考え方はport_module_instance_setting、設定を表す文字列をテーブルに格納することです (この特定のケースでは、valueフィールドが常に数値になるように条件が設定されています)。私が達成しようとしているのはvalue、これらの特定の「設定」のいずれかでフィールドが更新さ cust_profile_attributeれると、古いものによって参照されるテーブル内のすべてvalueが削除されることです。このコンテキストでは、valueフィールド ofport_module_instance_settingは、 of を直接参照する数値の varchar 値attribute_group_idですcore_attribute。実際のテーブル構造を制御できないため、異なるデータ型を使用したテーブルの参照に関するベスト プラクティスについてコメントしないでください :) トリガー内のすべてが適切に機能します。DELETE最後に声明。何もしていません。必要な属性を削除しない理由についてのアイデアはありますか?

更新前のフィールドDELETEを参照するように、ステートメントを次のように変更しました。value

DELETE FROM cust_profile_attribute
WHERE attribute_id IN(SELECT ISNULL(attribute_id,-1) FROM deleted d
                      JOIN core_attribute ca ON ca.attribute_group_id= CONVERT(INT,d.value))
于 2012-08-02T14:48:37.037 に答える