我在SQL Server 2012触发器上做错了什么?

时间:2016-06-16 13:27:33

标签: sql triggers

我无法得到应该是一个简单的触发工作。 它在INSERT之后触发,测试列A是否为空,如果是,则将其设置为同一行上的列B的值。 插入后,我检查插入的行,列B有一个值,但列A为空。 触发器已启用并被触发,因为在绝望中我将值记录到各个点的工作表中, 这些价值是预期的。

我甚至试图通过进入此表的Design并为此列指定1000的“默认值”来暂时绕过此问题,但它仍然是null。 我尝试更改触发器以将列A设置为固定值987,但它仍然是空的。

是否存在一些我不知道的插入特性?任何建议都表示赞赏。

背景---------------------------------------------- -------------------------------

OPTIONS是一个存储“选项”的表格,我们其中一个活动的参与者可以注册该选项(例如,活动门票,可选牛排或鸡肉晚餐等) 在定义事件时插入这些选项(日期,地点,联系信息以及与会者可以注册的选项)。

选项表:

OptionID INT  (Identity, primary key)
...
MaxAttendees INT
...
AvlbRemainingRegQty INT

最后一栏是没有设置的栏目 - 它应该是剩余的鸡肉晚餐剩余待售的总计

我以为我会发疯和/或做一些蠢事,所以我创建了一个zTestTrigger表来存储来自INSERTED行的值,并验证触发器是否达到某些点。

WhichPartOfTest VARCHAR(100)
OptionID        INT
AvlbRemRegQty   INT
MaxAttendees    INT

- DETAILS -------------------------------------------- -------

USE [dbname]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER TRIGGER [dbo].[trig_Options_AvlbRemainingRegQty]
ON [dbo].[Options]
AFTER INSERT
AS
SET NOCOUNT ON

DECLARE @I_OptionID INT
DECLARE @I_AvlbRemainingRegQty INT
DECLARE @I_MaxAttendees INT

SELECT
    @I_OptionID            = I.OptionID,
    @I_AvlbRemainingRegQty = ISNULL(I.AvlbRemainingRegQty,-1),
    @I_MaxAttendees        = MaxAttendees
FROM Inserted I

insert into zTestTrigger values ('Start of new test - values from INSERTED row are:',@I_OptionID, @I_AvlbRemainingRegQty, @I_MaxAttendees)

IF ISNULL(@I_AvlbRemainingRegQty,-1) = -1 --(I had also tried checking IF I_AvlbRemainingRegQty IS NULL)

    begin

    insert into zTestTrigger values ('About to update table, setting AvlbRemQty = ' + cast(@I_MaxAttendees as varchar) + ' where id = ' + cast(@I_OptionID as varchar),
@I_OptionID, @I_AvlbRemainingRegQty, @I_MaxAttendees)

    UPDATE Options SET AvlbRemainingRegQty = @I_MaxAttendees WHERE OptionID = @I_OptionID

    --Originally, I tried this:
    --UPDATE OPTIONS SET AvlbRemainingRegQty = ISNULL(MaxAttendees,1000) WHERE OptionID = @I_OptionID
    --This doesn't work either:
    --UPDATE OPTIONS SET SET AvlbRemainingRegQty = SELECT ISNULL(MaxAttendees,1000) FROM Options WHERE OptionID = @I_OptionID) WHERE OptionID = @I_OptionID
    --I even tried:
    --UPDATE OPTIONS SET AvlbRemainingRegQty = 987    WHERE OptionID = @I_OptionID

    declare @error int
    set @error = @@ERROR
    insert into zTestTrigger values ('@@ERROR is ' + cast(@error as varchar), 0,0,0) --Shows that @Error is 0

    end

从zTestTrigger表中选择显示

   "About to update table, setting AvlbRemQty = 1000 where id = 491" , 491, -1, and 1000

我可以选择ID为491的行,但其Avlb Rem数量为空。

1 个答案:

答案 0 :(得分:1)

我会个人使用instead of触发器,因为它允许我们从一开始就正确地输入数据。

但就目前而言,我们会在触发后进行:

ALTER TRIGGER [dbo].[trig_Options_AvlbRemainingRegQty]
ON [dbo].[Options]
AFTER INSERT
AS
   SET NOCOUNT ON

   UPDATE Options
   SET
      AvlbRemainingRegQty = COALESCE(AvlbRemainingRegQty, MaxAttendees)
   WHERE
      OptionID in (select OptionID from inserted)

请注意触发器(与您的不同)可识别inserted可包含0,1或多个行。因此将视为一个表,而不是将单独的标量变量分配给有意义的值。

正如另一点:

  

它应该是剩余的剩余鸡肉晚餐的总计

总的来说,这是一个坏主意。如果您要单独存储每笔销售的详细信息,则剩余的数字是可以计算的值。您只需存储这样的值,就可以让存储的值与其他数据不一致