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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL Server触发器认为没有时表中存在重复相关的知识,希望对你有一定的参考价值。

我是一个新的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;

以上是关于SQL Server触发器认为没有时表中存在重复的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 表中存在 UDT [重复]

如何在 SQL Server 表中添加“最后修改”和“创建”列?

SQL Server 在多个线程中插入死锁

如何获取在 SQL Server 内部数据库的不同表中重复的列[重复]

Sql server中有没有replace语句? 没有的话,怎样实现类似于mySql中的repla

sqlserver2005触发器问题