在SQL Server触发器中包含If语句?

时间:2019-11-20 01:49:32

标签: sql sql-server triggers

我目前正在努力学习数据库管理课程。我的任务是创建一个触发器,如果​​客户第一次进行预订,该触发器将打印一条消息。到目前为止,我的代码如下

ALTER TRIGGER [dbo].[ResNewTrigger] 
ON [dbo].[Reservation] 
AFTER INSERT, DELETE, UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    DECLARE @cid CHAR(4)   
    DECLARE @res_counts INT    
    SELECT @cid = CustomerNum FROM inserted    

    SELECT @res_counts = COUNT(*) 
    FROM dbo.Reservation 
    WHERE CustomerNum = @cid 

    IF @res_counts = 0 THEN
        PRINT  'A reservation is made for the first time from customer' + @cid;
    END IF;
END;

这会引发错误:

  

消息156,级别15,状态1,过程ResNewTrigger,第20行[批处理开始第7行]
  关键字“ THEN”附近的语法不正确。

     

第102行,状态15,状态1,消息ResNewTrigger,第22行[批处理开始第7行]
  ';'附近的语法不正确。

我一定不知道正确的语法或某些内容,但是我很幸运地发现如何解决此问题。

1 个答案:

答案 0 :(得分:1)

IF语句中的语法错误是与触发器有关的最少问题(请参见docs来更正IF语句)。

您的触发器是错误的,因为您假设inserted有一行。这样的假设永远都不安全。

ALTER TRIGGER [dbo].[ResNewTrigger] 
   ON  [dbo].[Reservation] 
   AFTER INSERT
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    DECLARE @cids VARCHAR(MAX);

    -- Insert statements for trigger here
    SELECT @cids = STRING_AGG(i.cid, ', ')
    FROM inserted i JOIN
         Reservation r
         ON r.customerNum = i.customerNum
    GROUP BY i.cid
    HAVING COUNT(*) = 1;   -- this row is already in reservation
    IF @cids <> ''
    BEGIN
        PRINT  'A reservation is made for the first time from customer(s) ' + @cids;
    END;
END;

这使用string_agg()将cid连接在一起。在早期版本的SQL Server中,您需要UDF或其他某种机制来聚合字符串。

我很好地卸下了触发器的UPDATEDELETE部分。您当然无法在DELETE上为客户获得新的预订。在UPDATE上,这更成问题。但是,很难(但不是不可能)区分对单个记录的更改和插入单个记录。