我的sql server 2008数据库上有以下触发器
CREATE TRIGGER tr_check_stoelen
ON Passenger
AFTER INSERT, UPDATE
AS
BEGIN
IF EXISTS(
SELECT 1
FROM Passenger p
INNER JOIN Inserted i on i.flight= p.flight
WHERE p.flight= i.flightAND p.seat= i.seat
)
BEGIN
RAISERROR('Seat taken!',16,1)
ROLLBACK TRAN
END
END
当我尝试运行下面的查询时,触发器会抛出错误。这个查询我应该在两个不同的航班上的数据库中插入两个不同的乘客。我确定两个座位都没有被占用,但我无法弄清楚为什么触发器会给我错误。是否必须对相关做些什么?
INSERT INTO passagier VALUES
(13392,5315,3,'Janssen Z','2A','October 30, 2006 10:43','M'),
(13333,5316,2,'Janssen Q','2A','October 30, 2006 11:51','V')
更新: 该表如下所示
CREATE TABLE Passagier
(
passengernumber int NOT NULL CONSTRAINT PK_passagier PRIMARY KEY(passagiernummer),
flight int NOT NULL CONSTRAINT FK_passagier_vlucht REFERENCES vlucht(vluchtnummer)
ON UPDATE NO ACTION ON DELETE NO ACTION,
desk int NULL CONSTRAINT FK_passagier_balie REFERENCES balie(balienummer)
ON UPDATE NO ACTION ON DELETE NO ACTION,
name varchar(255) NOT NULL,
seat char(3) NULL,
checkInTime datetime NULL,
gender char(1) NULL
)
答案 0 :(得分:6)
此子查询存在一些问题:
SELECT 1
FROM Passenger p
INNER JOIN Inserted i on i.flight= p.flight
WHERE p.flight= i.flight AND p.seat= i.seat
首先,WHERE p.flight = i.flight
是非常不必要的,因为它已经是您加入的一部分。
其次,p.seat = i.seat
也应该是JOIN
的一部分。
第三,此触发器在插入行之后运行,因此总是匹配,因此您的触发器总是引发错误并回滚。
您可以修复触发器,但更好的方法是根本不使用触发器。如果我了解您要正确执行的操作,则只需UNIQUE
对flight, seat
ALTER TABLE passgier
ADD CONSTRAINT IX_passagier_flightseat
UNIQUE (flight, seat)
约束:
{{1}}
答案 1 :(得分:2)
如果在插入记录后运行触发器,然后查找包含刚刚插入的值的记录,则始终可以找到它。您可以尝试使用INSTEAD OF触发器,以便在实际插入之前检查现有记录。
答案 2 :(得分:0)
它可能通过在表中找到自己来抛出错误(循环引用回到自身)。您可能希望在where子句中添加其他过滤器,例如“AND Passenger.ID<> inserted.ID”