Ваш триггер не за горами, но на самом деле вы могли бы использовать триггер INSTEAD OF
Создание тестовых данных
create table product ( productId int identity(1,1) constraint PK_product_productId primary key clustered, quantity_in_stock int )
create table order_detail ( order_id int
,productId int constraint FK_order_product_productId foreign key references product (productId)
,quantity int not null)
set identity_insert product on
insert into product (productId, quantity_in_stock) values ( 1, 100 ), ( 2, 25 ) , (3, 2);
Это «Работы» (в наименьшем смысле этого слова)
Принимая во внимание комментарии Мартина, необходимо определить productid
для quantity_in_stock
.
CREATE TRIGGER tr_check_qty
ON order_detail
FOR insert, update AS
DECLARE @stock int
DECLARE @neworder int
SELECT @stock = quantity_in_stock
From product
Where productid = (select productid from inserted)
SELECT @neworder = quantity FROM inserted
IF @neworder > @stock
BEGIN
PRINT 'NO WAY JOSE'
ROLLBACK TRANSACTION
END
Теперь все работает как надо ...
INSERT order_detail (order_id, productId, quantity)
values
(10044, 1, 30) -- works as stock is 100
,(10044, 3, 1)
insert order_detail (order_id, productId, quantity)
values
(10044, 1, 130) /* fails (CORRECTLY) WITH Msg 3609, Level 16... (transacted ended in the trigger..) */
/* this should work... */
UPDATE order_detail
SET quantity = 30
WHERE order_id = 10044
AND productid = 1
/* this should fail.. */
UPDATE order_detail
SET quantity = 3000 /*< not enough stock. */
WHERE order_id = 10044
AND productid = 1
А если обратиться к первому пункту Мартинса, этот подход лучше:
CREATE TRIGGER tr_check_qty
ON order_detail
FOR insert, update AS
DECLARE @stock int
DECLARE @neworder int
if(exists(select *
from inserted i join product p on i.productId = p.productId
where i.quantity > p.quantity_in_stock))
begin
PRINT 'NO WAY JOSE'
ROLLBACK TRANSACTION
End