轻松触发问题

时间:2010-11-04 19:55:50

标签: sql-server tsql triggers

我认为对于那些使用T-SQL,尤其是触发器工作很多的人来说,这将是一个简单的问题:

我希望对此表的所有更新和插入强制执行以下约束:

  1. 如果DiscountTypeId = 1,则FlatFee不得为NULL。
  2. 如果DiscountTypeId = 2,则DiscountRate不得为空。
  3. 如果在插入或更新表中这两个条件中的任何一个失败,我想返回一个适当的错误。

    触发器似乎还没有做任何事情。 。您可以提供必要的更改,使其按照描述执行吗?

    USE [PandaVisa2008]
    GO
    
    /****** Object:  Table [dbo].[CustomerSpeed]    Script Date: 11/04/2010 15:51:10 ******/
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    CREATE TABLE [dbo].[CustomerSpeed](
     [CustomerSpeedId] [int] NOT NULL,
     [CustomerId] [int] NULL,
     [SpeedId] [int] NOT NULL,
     [DiscountTypeId] [int] NOT NULL,
     [FlatFee] [money] NULL,
     [DiscountRate] [decimal](3, 3) NULL,
     CONSTRAINT [PK_AgentFee] PRIMARY KEY CLUSTERED 
    (USE [PandaVisa2008]
    
    GO
    
    /****** Object:  Trigger [dbo].[TRG_CustomerSpeed_OnInsertUpdate]    Script Date: 11/04/2010 15:38:06 ******/
    SET ANSI_NULLS ON
    
    GO
    
    SET QUOTED_IDENTIFIER ON
    
    GO
    
    ALTER TRIGGER [dbo].[TRG_CustomerSpeed_OnInsertUpdate]
    ON [dbo].[CustomerSpeed]
    FOR INSERT, UPDATE
    AS
        BEGIN
    
            DECLARE @DiscountTypeId INT
            DECLARE @FlatFee MONEY
            DECLARE @DiscountRate DECIMAL(3, 3)
    
            SELECT
                @DiscountTypeId = DiscountTypeId,
                @FlatFee = FlatFee,
                @DiscountRate = DiscountRate
            FROM
                inserted
    
            IF @DiscountTypeId = 1
               AND @FlatFee IS NULL
                BEGIN
                    RAISERROR (N'If @DiscountTypeId is 1, FlatFee must not be NULL',
                               10,
                               1)
                END
    
      IF @DiscountTypeId = 2
               AND @DiscountRate IS NULL
                BEGIN
                    RAISERROR (N'If @DiscountTypeId is 2, @DiscountRate must not be NULL',
                               10,
                               1)
                END            
        END 
    
     [CustomerSpeedId] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    
    GO
    
    ALTER TABLE [dbo].[CustomerSpeed]  WITH CHECK ADD  CONSTRAINT [CK_CustomerSpeed] CHECK  (([DiscountRate]>(0) AND [DiscountRate]<(1)))
    GO
    
    ALTER TABLE [dbo].[CustomerSpeed] CHECK CONSTRAINT [CK_CustomerSpeed]
    GO
    

    修改

    我得到了它的工作。我没有读过触发器来弥补我基本上缺乏理解,但他似乎工作,虽然我相信Check Constraint是更好的方法:

    ALTER TRIGGER [dbo].[TRG_CustomerSpeed_OnInsertUpdate]
    ON [dbo].[CustomerSpeed]
    FOR INSERT, UPDATE
    AS
        BEGIN
            IF EXISTS (SELECT
                           1
                       FROM
                           inserted I
                       WHERE  I.DiscountTypeId = 1
                          AND I.FlatFee IS NULL)
                BEGIN
                    ROLLBACK TRANSACTION
    
                    RAISERROR (N'If DiscountTypeId is 1, FlatFee must not be NULL',
                               10,
                               1)
                END
    
           IF EXISTS (SELECT
                           1
                       FROM
                           inserted I
                       WHERE  I.DiscountTypeId = 2
                          AND I.DiscountRate IS NULL)
                BEGIN
                    ROLLBACK TRANSACTION
    
                    RAISERROR (N'If DiscountTypeId is 2, DiscountRate must not be NULL',
                               10,
                               1)
                END            
        /*
         IF @DiscountTypeId = 2
            AND @DiscountRate IS NULL
             BEGIN
             Rollback Transaction
                 RAISERROR (N'If @DiscountTypeId is 2, DiscountRate must not be NULL',
                            10,
                            1)
             END
        */
        END 
    
    Your comments are welcomed.
    

3 个答案:

答案 0 :(得分:5)

我使用CHECK约束,而不是触发器

ALTER TABLE Mytable WITH CHECK ADD
   CONSTRAINT CK_MyTable_GoodName CHECK (
        NOT (DiscountTypeId = 1 AND Flatfee IS NULL)
        AND
        NOT (DiscountTypeId = 2 AND DiscountRate IS NULL)
)

另外,需要考虑“如果DiscountTypeId&lt;&gt; 1,Flatfee必须为NULL”等等

答案 1 :(得分:1)

你从根本上不理解触发器。您需要做的第一件事是阅读有关联机丛书中的触发器,特别强调了解插入和删除的psuedotables。接下来你需要知道的是触发器应该永远不会被写入,就好像它一次只能处理一条记录一样。触发器对批量记录进行操作,触发器代码必须考虑到这一点。

答案 2 :(得分:0)

我不相信触发器会引发错误,问题#1。