我是一个新的SQL开发人员。建议后我改变了我的触发器(对于这个任务,我需要使用一个触发器,所以无法避免它),但我已经重新改变了我的触发器。我希望它能防止Rentals
表中包含BikeID
外键的重复。
这是我目前的代码:
CREATE TRIGGER BikeNotAvailable
ON dbo.SA_Rental
AFTER INSERT
AS
IF EXISTS (SELECT *
FROM SA_Rental
INNER JOIN inserted i ON i.BikeID = dbo.SA_Rental.BikeID)
BEGIN
ROLLBACK
RAISERROR ('This bike is already being hired', 16, 1);
END
go
但是当我在BikeID
表中输入Rentals
时,即使BikeID
在一行中还没有出现,它仍然会引发错误 - 为什么? (我还在空表上测试了它,但它仍然会引发错误)
在我的数据的一些上下文中,BikeID
是来自'Bike'表的主键,它作为Rentals
表的外键共享,不确定这是否与错误有关。
有人可以帮我修复这个触发器,以便它可以工作。
谢谢。
好吧,因为它是一个AFTER触发器,触发器在新记录添加到表格后运行(至少对于触发器是可见的)。
假设您的表具有自动生成的ID列,您应该从支票中排除插入的行,如下所示:
CREATE TRIGGER BikeNotAvailable ON dbo.SA_Rental
AFTER INSERT
AS
if exists ( select * from SA_Rental
inner join inserted i on i.BikeID=dbo.SA_Rental.BikeID
where SA_Rental.RentalID <> i.RentalID)
begin
rollback
RAISERROR ('This bike is already being hired', 16, 1);
end
go
实现目标的一种更简单的方法是创建一个唯一索引:
CREATE UNIQUE INDEX BikeRented ON SA_Rental (BikeID);
当然,这假设您在不再租用自行车时从表中删除行(因为这是您帖子中隐含的逻辑)。如果不是这样,那么我们需要更多细节;在您的桌子上指明租赁已完成?
如果我们假设你有一个返回日期,并且当自行车尚未返回时返回日期是NULL
,那么你将使用过滤索引,如下所示:
CREATE UNIQUE INDEX BikeRented ON SA_Rental (BikeID)
WHERE ReturnedDate IS NULL;