在 SQL 中触发导致错误 "Product_Reorder is not a recognized SET option"
Trigger in SQL causing error "Product_Reorder is not a recognized SET option"
CREATE OR ALTER TRIGGER CheckQuantity
ON dbo.Products
AFTER UPDATE
AS
BEGIN
UPDATE dbo.Products
SET Product_ReOrder = 1
FROM Inserted i
WHERE i.Product_ID = dbo.Products.Product_ID
AND i.Product_QOH < 5;
我没有收到语法错误
syntax error near ;
这是指代码末尾的;
。
不是 100% 确定您要做什么 - 您也没有给我们太多可以继续的东西!
我假设你的意思是你想在你的table中设置一个名为Product_ReOrder
的列如果另一列 Product_QOH
小于 5,则为 1 - 正确吗?
在这种情况下 - 使用类似这样的触发器:
CREATE OR ALTER TRIGGER CheckQuantity
ON dbo.Products
AFTER UPDATE
AS
BEGIN
UPDATE dbo.Products
SET Product_ReOrder = 1
FROM Inserted i
WHERE i.PrimaryKeyColumn = dbo.Products.PrimaryKeyColumn
AND i.Product_QOH < 5;
END
触发器将在 UPDATE
之后触发,并且 Inserted
将包含 所有 行(可以并且 将 是多行!)已更新 - 所以我假设您想检查这些行的数量。
我正在将基数 table (dbo.Products
) 加入到 Inserted
伪 table 上 table 的主键列(其中我们不知道它是什么 - 所以你需要根据需要调整它),如果 Products_QOH
值小于 5,我将 Product_ReOrder
列设置为 1。
你的代码行
Select @QOH = (select Product_QOH from inserted)
有一个致命缺陷假设只更新了一行 - 有时可能是这种情况 - 但你不能依赖那!您的触发器 必须能够 处理正在更新的多行 - 因为触发器仅被调用 一次 ,即使使用命令更新了 10 行 -然后 Inserted
将包含所有这 10 个更新的行。这样做 select 是危险的 - 你会得到 一个任意的 行,而你将忽略所有其他行....
这就是你要找的吗?
我不清楚您在编写这段代码时在想什么,或者您基于什么模板,但是有很多语法错误。
看来您可能想要这样的东西:
update()
函数只告诉我们该列是否出现在 update
语句中,而不告诉我们是否有任何实际更改。
- 我们需要检查我们是否被递归调用,以便退出。
- 我们还会检查是否根本没有更改任何行,并尽早退出
- 请注意如何比较
inserted
和 deleted
以查看是否有任何行实际更改。这也可以正确处理多行。
- 然后我们需要重新加入
Products
以更新它。
create or alter trigger CheckQuantity
on Products
after update
as
set nocount on;
if not(update(Products_QOH))
or trigger_nestlevel(object_id(N'dbo.CheckQuantity'),'AFTER','DML') > 1
or not exists (select 1 from inserted)
return; -- early bail-out
update p
set Product_ReOrder = 1
from Products p
join (
select i.YourPrimaryKey, i.Products_QOH
from inserted i
where i.Product_QOH < 5
except
select d.YourPrimaryKey, d.Products_QOH
from deleted d
) i on i.YourPrimaryKey = p.YourPrimaryKey;
但是,我完全不明白你为什么要使用触发器。
我强烈建议您为此使用计算列:
ALTER TABLE Products
DROP COLUMN Product_ReOrder;
ALTER TABLE Products
ADD Product_ReOrder AS (CASE WHEN Product_QOH < 5 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END);
CREATE OR ALTER TRIGGER CheckQuantity
ON dbo.Products
AFTER UPDATE
AS
BEGIN
UPDATE dbo.Products
SET Product_ReOrder = 1
FROM Inserted i
WHERE i.Product_ID = dbo.Products.Product_ID
AND i.Product_QOH < 5;
我没有收到语法错误
syntax error near ;
这是指代码末尾的;
。
不是 100% 确定您要做什么 - 您也没有给我们太多可以继续的东西!
我假设你的意思是你想在你的table中设置一个名为Product_ReOrder
的列如果另一列 Product_QOH
小于 5,则为 1 - 正确吗?
在这种情况下 - 使用类似这样的触发器:
CREATE OR ALTER TRIGGER CheckQuantity
ON dbo.Products
AFTER UPDATE
AS
BEGIN
UPDATE dbo.Products
SET Product_ReOrder = 1
FROM Inserted i
WHERE i.PrimaryKeyColumn = dbo.Products.PrimaryKeyColumn
AND i.Product_QOH < 5;
END
触发器将在 UPDATE
之后触发,并且 Inserted
将包含 所有 行(可以并且 将 是多行!)已更新 - 所以我假设您想检查这些行的数量。
我正在将基数 table (dbo.Products
) 加入到 Inserted
伪 table 上 table 的主键列(其中我们不知道它是什么 - 所以你需要根据需要调整它),如果 Products_QOH
值小于 5,我将 Product_ReOrder
列设置为 1。
你的代码行
Select @QOH = (select Product_QOH from inserted)
有一个致命缺陷假设只更新了一行 - 有时可能是这种情况 - 但你不能依赖那!您的触发器 必须能够 处理正在更新的多行 - 因为触发器仅被调用 一次 ,即使使用命令更新了 10 行 -然后 Inserted
将包含所有这 10 个更新的行。这样做 select 是危险的 - 你会得到 一个任意的 行,而你将忽略所有其他行....
这就是你要找的吗?
我不清楚您在编写这段代码时在想什么,或者您基于什么模板,但是有很多语法错误。
看来您可能想要这样的东西:
update()
函数只告诉我们该列是否出现在update
语句中,而不告诉我们是否有任何实际更改。- 我们需要检查我们是否被递归调用,以便退出。
- 我们还会检查是否根本没有更改任何行,并尽早退出
- 请注意如何比较
inserted
和deleted
以查看是否有任何行实际更改。这也可以正确处理多行。 - 然后我们需要重新加入
Products
以更新它。
create or alter trigger CheckQuantity
on Products
after update
as
set nocount on;
if not(update(Products_QOH))
or trigger_nestlevel(object_id(N'dbo.CheckQuantity'),'AFTER','DML') > 1
or not exists (select 1 from inserted)
return; -- early bail-out
update p
set Product_ReOrder = 1
from Products p
join (
select i.YourPrimaryKey, i.Products_QOH
from inserted i
where i.Product_QOH < 5
except
select d.YourPrimaryKey, d.Products_QOH
from deleted d
) i on i.YourPrimaryKey = p.YourPrimaryKey;
但是,我完全不明白你为什么要使用触发器。
我强烈建议您为此使用计算列:
ALTER TABLE Products
DROP COLUMN Product_ReOrder;
ALTER TABLE Products
ADD Product_ReOrder AS (CASE WHEN Product_QOH < 5 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END);