在 SQL 中触发导致错误“Product_Reorder 不是可识别的 SET 选项”
Posted
技术标签:
【中文标题】在 SQL 中触发导致错误“Product_Reorder 不是可识别的 SET 选项”【英文标题】:Trigger in SQL causing error "Product_Reorder is not a recognized SET option" 【发布时间】:2021-11-28 20:35:13 【问题描述】: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;
我没有收到语法错误
; 附近的语法错误
这里指的是代码末尾的;
。
【问题讨论】:
触发器是高度特定于供应商的 - 所以请添加标签以指定您使用的是mysql
、postgresql
、sql-server
、oracle
还是db2
- 或完全不同的东西。
触发器是高度特定于供应商的,因此您需要标记您的数据库。也就是说,您所展示的内容绝不是任何方言中的有效 SQL。
好的,我添加了标签
Stu,这显然不是有效的 SQL,这就是我需要帮助的原因。
您的具体错误是因为set
不是您在 SQL Server 或任何 RDBMS 中 更新 行的方式;更新您使用update table set <columns>
的值,但是您在问题中描述的内容并不足以继续确定您的期望;我建议通过trigger tutorial
【参考方案1】:
不是 100% 确定您要做什么 - 您也没有给我们太多的帮助!
我假设您的意思是,如果另一列 Product_QOH
小于 5,您希望将表中名为 Product_ReOrder
的 列 设置为 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
将包含已更新的 所有 行(可以和 将 是多行!) - 所以我假设您想检查这些行的数量。
我将基表 (dbo.Products
) 加入到表主键列上的 Inserted
伪表中(我们不知道它是什么 - 所以您需要根据需要进行调整) ,如果Products_QOH
值小于5,我将Product_ReOrder
列设置为1。
你的代码行
Select @QOH = (select Product_QOH from inserted)
有一个致命缺陷,即假设只更新了一行 - 有时可能会出现这种情况 - 但您不能依赖!您的触发器必须能够处理更新的多行 - 因为触发器仅被调用 一次,即使使用命令更新了 10 行 - 然后Inserted
将包含所有这 10 个更新的行。做这样的选择是危险的——你会得到一个任意的行,你会忽略所有其他的......
这就是你要找的吗?
【讨论】:
所以我需要做的是设置一个触发器来更新 Product_Reorder 当 Products_QOH 小于 5 时它有点为 1。当我使用此代码时,它在“5”附近给了我不正确的语法;" @TassoPsaltakis:抱歉 - 有错字(Products_QOH
末尾有额外的“s” - 似乎是 Product_QOH
- 试试我更新的触发器。这有点令人困惑 因为您的问题中有两种拼写(末尾有和没有“s”)......
我在你提到的代码中也看到了主键但是我在这个表中没有任何键
@TassoPsaltakis:每个表都应该有一个主键!
@TassoPsaltakis 我遇到语法错误 从来都不是有用的东西。并且 cmets 不适用于添加有关您的问题的其他代码和详细信息。此外,很难猜测您实际编写的代码以及它是如何执行/测试的。很简单,您需要比 SO 这样的技术问答论坛提供的更多帮助。在尝试触发器之前,您需要掌握 tsql。而且设计数据库是一项与编写 tsql 非常不同的技能——这是你需要学习的其他东西。【参考方案2】:
我不清楚您在编写此代码时在想什么,或者您基于什么模板,但有很多语法错误。
看来你可能想要这样的东西:
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);
【讨论】:
我需要使用触发器。 IT 用于一项任务。我们应该使用没有任何键的表。我只需要获取一列的值,然后更新另一列。 如果您有一个没有键的表,那么您需要重新考虑您的架构。如果这是给你的,我建议你和你的老师谈谈适当的数据库规范化的必要性以上是关于在 SQL 中触发导致错误“Product_Reorder 不是可识别的 SET 选项”的主要内容,如果未能解决你的问题,请参考以下文章
ORDER BY 中带有 CASE WHEN 的 SQL 语句导致类型转换错误