我想制作一个触发器,我可以检查产品0的库存中的值是否为。 然后触发器应该使值为1。
我的触发器
CREATE TRIGGER [IfStockIsNull]
ON [dbo].[Products]
FOR DELETE, INSERT, UPDATE
AS
BEGIN
if [Products].Stock = 0
UPDATE [Products] SET [Stock] = 1
FROM [Products] AS m
INNER JOIN inserted AS i
ON m.ProductId = i.ProductId;
ELSE
raiserror('Niks aan het handje',10,16);
END
我收到了错误:
Altering [dbo].[IfStockIsNull]...
(53,1): SQL72014: .Net SqlClient Data Provider: Msg 4104, Level 16, State 1,
Procedure IfStockIsNull, Line 7 The multi-part identifier "Products.Stock"
could not be bound.
(47,0): SQL72045: Script execution error. The executed script:
ALTER TRIGGER [IfStockIsNull]
ON [dbo].[Products]
FOR DELETE, INSERT, UPDATE
AS BEGIN
IF [Products].Stock = 0
UPDATE [Products]
SET [Stock] = 1
FROM [Products] AS m
INNER JOIN
inserted AS i
ON m.ProductId = i.ProductId;
ELSE
RAISERROR ('Niks aan het handje', 10, 16);
END
An error occurred while the batch was being executed.
也许你们可以帮助我?
答案 0 :(得分:3)
您尝试在此处运行的许多问题和惊喜。但基本上,当您处理集时,不要尝试运行程序步骤。 inserted
可以包含0,1或多个行,因此您在IF
中询问哪个行的股票?
最好在WHERE
子句中处理它:
CREATE TRIGGER [IfStockIsNull]
ON [dbo].[Products]
FOR INSERT, UPDATE --Removed DELETE, because ?!?
AS
BEGIN
UPDATE [Products] SET [Stock] = 1
FROM [Products] AS m
INNER JOIN inserted AS i
ON m.ProductId = i.ProductId;
WHERE m.Stock = 0
--Not sure what the error is for - the above update may have updated
--some number of rows, between 0 and the number in inserted.
--What circumstances should produce an error then?
END
UPDATE
的简单演示脚本正确定位inserted
中匹配的行:
declare @t table (ID int not null, Val int not null)
insert into @t(ID,Val) values (1,1),(2,2),(3,3)
update
@t
set
Val = 4
from
@t t
inner join
(select 2 as c) n
on
t.ID = n.c
select * from @t
显示只更新ID
2
的行。
即使是Microsoft的自己的UPDATE ... FROM
syntax示例也使用了Gordon声称不起作用的UPDATE <table> ... FROM <table> <alias> ...
语法:
USE AdventureWorks2012;
GO
UPDATE Sales.SalesPerson
SET SalesYTD = SalesYTD + SubTotal
FROM Sales.SalesPerson AS sp
JOIN Sales.SalesOrderHeader AS so
ON sp.BusinessEntityID = so.SalesPersonID
AND so.OrderDate = (SELECT MAX(OrderDate)
FROM Sales.SalesOrderHeader
WHERE SalesPersonID = sp.BusinessEntityID);
GO
此示例确实有一个问题,在下面进一步说明但是与“其他表中的多个匹配行只会导致单个更新”的缺陷是任何使用{{1应该让自己意识到。
答案 1 :(得分:1)
如果你想在任何行不好的情况下停止插入,那么在进行更改之前执行:
ALTER TRIGGER [IfStockIsNull] ON [dbo].[Products]
FOR INSERT, UPDATE -- DELETE is not really appropriate
AS BEGIN
IF (EXISTS (SELECT 1
FROM Products p JOIN
inserted i
ON m.ProductId = i.ProductId
WHERE p.Stock = 0
)
)
BEGIN
RAISERROR ('Niks aan het handje', 10, 16);
END;
UPDATE p
SET Stock = 1
FROM Products p INNER JOIN
inserted AS i
ON p.ProductId = i.ProductId;
END;
注意:
IF
中的比较检查Product
行中是否有0
行。如果是,则回滚整个事务。INSERT
中的任何行失败,则会回滚整个INSERT
,而不仅仅是一行。UPDATE
不正确,因为Products
子句和FROM
子句中有UPDATE
。您需要使用第一个别名。