在 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;

我没有收到语法错误

; 附近的语法错误

这里指的是代码末尾的;

【问题讨论】:

触发器是高度特定于供应商的 - 所以请添加标签以指定您使用的是mysqlpostgresqlsql-serveroracle 还是db2 - 或完全不同的东西。 触发器是高度特定于供应商的,因此您需要标记您的数据库。也就是说,您所展示的内容绝不是任何方言中的有效 SQL。 好的,我添加了标签 Stu,这显然不是有效的 SQL,这就是我需要帮助的原因。 您的具体错误是因为set 不是您在 SQL Server 或任何 RDBMS 中 更新 行的方式;更新您使用update table set &lt;columns&gt; 的值,但是您在问题中描述的内容并不足以继续确定您的期望;我建议通过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 语句中,而不是实际更改了任何内容。 我们需要检查我们是否被递归调用,以便摆脱困境。 我们还会检查是否根本没有更改任何行,并尽早退出 注意如何比较 inserteddeleted 以查看是否有任何行实际更改。这也能正确处理多行。 然后我们需要重新加入 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 选项”的主要内容,如果未能解决你的问题,请参考以下文章

登录到 SQL Server 触发器中的表

在mysql中触发导致错误

SQL Server 触发器插入导致锁定直到提交

ORDER BY 中带有 CASE WHEN 的 SQL 语句导致类型转换错误

sql 触发器在将列名存储在变量中并将其用于 sql 触发器中的 OLD.myvar 时出现错误

SQL - 触发更新错误