我尝试创建一个触发器,如果数量大于orderdetails
表中的unitsinstock
,则会阻止用户更新products
表中的数量
我是新手,并尝试阅读我在微软的T-SQL文档here中可以找到的内容,但没有发现它太有用了。
这是我得到的错误:
Msg 512,Level 16,State 1,Procedure tr_check_qty,Line 281 [Batch Start Line 0]
子查询返回的值超过1。当子查询遵循=,!=,<,< =,>,> =或子查询用作表达式时,不允许这样做。
有人有什么建议吗?
CREATE TRIGGER tr_check_qty
ON orderdetails
FOR UPDATE
AS
DECLARE @prod_id INT
SELECT @prod_id = productid
FROM inserted
IF (SELECT products.UnitsInStock
FROM products
WHERE products.productid = @prod_id) >= (SELECT orderdetails.quantity
FROM orderdetails
WHERE orderdetails.productid = @prod_id)
BEGIN
ROLLBACK TRANSACTION
PRINT 'Not enough units in stock.'
END
GO
答案 0 :(得分:0)
消息很清楚,你的一个选择会返回多于1个值,因此无法进行比较,因为它不知道必须比较哪些值。
这是您要编写的代码(您只需要为更新的orderdetail检索产品数量):
create trigger tr_check_qty
ON orderdetails
FOR UPDATE
AS
DECLARE @orderdetail_id int
DECLARE @prod_id int
select @orderdetail_id = orderdetailid, @prod_id = productid
FROM inserted
IF(
select UnitsInStock
from products
where productid = @prod_id
)
>=
(
select quantity
from orderdetails
where orderdetailid = @orderdetail_id and productid = @prod_id
)
BEGIN
ROLLBACK TRANSACTION
PRINT 'Not enough units in stock.'
END
GO
这仅在您逐个修改记录时才有效(因此插入的虚拟表只有一条记录)。但是迟早你会尝试在一条指令上更新几个orderdetails,并且你的触发器不会遍历每个更新的产品。为此,您需要一个光标。
我还用raiserror替换了你的回滚(也回滚了事务)。
create trigger tr_check_qty
ON orderdetails
FOR UPDATE
AS
DECLARE @orderdetail_id int
DECLARE @prod_id int
DECLARE UpdatedProducts CURSOR FOR select orderdetailid, productid from inserted
OPEN UpdatedProducts
FETCH NEXT FROM UpdatedProducts INTO @orderdetail_id, @product_id
WHILE @@fetch_status = 0
BEGIN
IF(
select UnitsInStock
from products
where products.productid = @prod_id
)
>=
(
select quantity
from orderdetails
where orderdetailid = @orderdetail_id and productid = @prod_id
)
BEGIN
CLOSE UpdatedProducts
DEALLOCATE UpdatedProducts
RAISERROR('Not enough units in stock.', 20, -1)
END
@FETCH NEXT FROM UpdatedProducts INTO @orderdetail_id, @product_id
END
CLOSE UpdatedProducts
DEALLOCATE UpdatedProducts
GO
但是,如果您直接将products表连接到插入的虚拟表,那么您可以构建一个更简单的触发器,对更新的每一行执行相同的检查。
create trigger tr_check_qty
ON orderdetails
FOR UPDATE
AS
IF exists(select *
from inserted
inner join products on products.productid = inserted.productid
where inserted.quantity > products.UnitsInStock)
begin
raiserror('Not enough units in stock.', 20, -1)
end
GO
答案 1 :(得分:0)
谢谢@Marc Guillot,我使用下面的代码使触发器工作,以满足问题中的两个更新(允许1个,不1个)。
.env