SQL 服务器触发器认为 table 中存在重复,但实际上没有
SQL Server trigger thinks there's a duplicate in the table when there isn't
我是一名新 SQL 开发人员。根据建议,我改变了我的触发器(为此任务我需要使用触发器所以无法避免),但我已经重新改变了我的触发器。我希望它能防止其中包含的 BikeID
外键的 Rentals
table 重复。
这是我目前的代码:
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
但是当我在 Rentals
table 中输入 BikeID
时,即使 BikeID
不在一行中,它仍然会引发错误 -为什么? (我也在空的 table 上测试过这个,它仍然会引发错误)
只是关于我的数据的一些上下文,BikeID
是来自 'Bike' table 的主键,作为外键共享到 Rentals
table,不确定这是否与错误有关。
谁能帮我修复这个触发器,让它工作。
谢谢。
好吧,因为它是一个 AFTER 触发器,触发器是 运行 在 新记录添加到 table 之后(至少对您的可见触发器)。
假设您的 table 有一个自动生成的 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);
当然,这 假设 当自行车不再租用时,您从 table 中删除了该行(因为这是您 post).如果不是这种情况,那么我们需要更多细节;在您的 table 上说明租赁已完成的是什么?
如果我们假设你有一个return日期,return日期是NULL
当自行车尚未 returned 时,您将使用如下过滤索引:
CREATE UNIQUE INDEX BikeRented ON SA_Rental (BikeID)
WHERE ReturnedDate IS NULL;
我是一名新 SQL 开发人员。根据建议,我改变了我的触发器(为此任务我需要使用触发器所以无法避免),但我已经重新改变了我的触发器。我希望它能防止其中包含的 BikeID
外键的 Rentals
table 重复。
这是我目前的代码:
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
但是当我在 Rentals
table 中输入 BikeID
时,即使 BikeID
不在一行中,它仍然会引发错误 -为什么? (我也在空的 table 上测试过这个,它仍然会引发错误)
只是关于我的数据的一些上下文,BikeID
是来自 'Bike' table 的主键,作为外键共享到 Rentals
table,不确定这是否与错误有关。
谁能帮我修复这个触发器,让它工作。
谢谢。
好吧,因为它是一个 AFTER 触发器,触发器是 运行 在 新记录添加到 table 之后(至少对您的可见触发器)。
假设您的 table 有一个自动生成的 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);
当然,这 假设 当自行车不再租用时,您从 table 中删除了该行(因为这是您 post).如果不是这种情况,那么我们需要更多细节;在您的 table 上说明租赁已完成的是什么?
如果我们假设你有一个return日期,return日期是NULL
当自行车尚未 returned 时,您将使用如下过滤索引:
CREATE UNIQUE INDEX BikeRented ON SA_Rental (BikeID)
WHERE ReturnedDate IS NULL;