我目前正在努力学习数据库管理课程。我的任务是创建一个触发器,如果客户第一次进行预订,该触发器将打印一条消息。到目前为止,我的代码如下
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行]';'附近的语法不正确。
我一定不知道正确的语法或其他内容,但是我很幸运地找到了解决这个问题的方法。
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或其他某种机制来聚合字符串。
我很好地去除了触发器的UPDATE
和DELETE
部分。您当然无法在DELETE
上为客户获得新的预订。在UPDATE
上,这更成问题。但是,很难(但不是不可能)区分对单个记录的更改和插入单个记录。