SQL Server触发器认为没有时表中存在重复

问题描述 投票:0回答:2

我是一个新的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表的外键共享,不确定这是否与错误有关。

有人可以帮我修复这个触发器,以便它可以工作。

谢谢。

sql sql-server triggers insert exists
2个回答
2
投票

好吧,因为它是一个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

2
投票

实现目标的一种更简单的方法是创建一个唯一索引:

CREATE UNIQUE INDEX BikeRented ON SA_Rental (BikeID);

当然,这假设您在不再租用自行车时从表中删除行(因为这是您帖子中隐含的逻辑)。如果不是这样,那么我们需要更多细节;在您的桌子上指明租赁已完成?

如果我们假设你有一个返回日期,并且当自行车尚未返回时返回日期是NULL,那么你将使用过滤索引,如下所示:

CREATE UNIQUE INDEX BikeRented ON SA_Rental (BikeID)
WHERE ReturnedDate IS NULL;
© www.soinside.com 2019 - 2024. All rights reserved.