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是直接引用attribute_group_idof的数字 varchar 值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 回答