为什么“子查询返回超过 1 个值。这是不允许的……”对于触发器中的相同查询而不是执行普通查询

发布于 2024-09-28 10:40:45 字数 609 浏览 2 评论 0原文

我仍在尝试正确使用触发器,但是当工作时,另一个触发器似乎再次开始(失败)。烦人..但也有教育意义:-)

当我在 MS SQL Server 中执行以下 SQL 时成功完成,但是当它在 AFTER UPDATE 触发器中执行时,它会失败并出现错误

消息 512,级别 16,状态 1,过程 TR_PHOTO_AU,第 37 行返回子查询 大于 1 的值。这不是 当子查询跟在 = 后面时允许 !=、<、<=、>、>= 或子查询时 用作表达式。

SQL;

        UPDATE p2
        SET p2.esb = '0'
        FROM ( SELECT TOP(5) p1.esb 
               FROM SOA.dbo.photos_TEST  p1
               WHERE  p1.esb = 'Q'
               ORDER BY p1.arrivaldatetime ASC 
        ) p2

为什么不允许在触发器中使用子查询作为表达式?有解决方法吗?

再次感谢, 彼得

I am still trying to get of triggers right, but when is working it seems the other starts (failing) again. Annoying.. but also educational :-)

When i executed the following SQL in MS SQL server is completes successfully, but when it is executed in a AFTER UPDATE trigger it fails with the error

Msg 512, Level 16, State 1, Procedure
TR_PHOTO_AU, Line 37 Subquery returned
more than 1 value. This is not
permitted when the subquery follows =,
!=, <, <= , >, >= or when the subquery
is used as an expression.

SQL;

        UPDATE p2
        SET p2.esb = '0'
        FROM ( SELECT TOP(5) p1.esb 
               FROM SOA.dbo.photos_TEST  p1
               WHERE  p1.esb = 'Q'
               ORDER BY p1.arrivaldatetime ASC 
        ) p2

Why is it not allowed to use a subquery as an expression in a trigger? And is there a workaround ?

thanks again,
Peter

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

下壹個目標 2024-10-05 10:40:45

必须在完全不同的方向找到解决方案,我不小心将触发器定义为插入后更新触发器而不是更新后触发器。以下触发器定义现在可以工作

CREATE TRIGGER TR_PHOTO_AU
   ON       SOA.dbo.photos_TEST
   AFTER    UPDATE
AS 

DECLARE @MAXCONC INT  -- Maximum concurrent processes
DECLARE @CONC INT     -- Actual concurrent processes

SET @MAXCONC = 1      -- 1 concurrent processes

-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON

-- If column esb is involved in the update, does not necessarily mean
-- that the column itself is updated
If ( Update(ESB) )
BEGIN
    -- If column esb has been changed to 1 or Q
    IF ((SELECT esb FROM INSERTED) in ('1','Q'))
    BEGIN
        -- count the number of (imminent) active processes
        SET @CONC = (SELECT COUNT(*) 
                  FROM SOA.dbo.photos_TEST pc
                  WHERE pc.esb in ('0','R'))

        -- if maximum has not been reached
        IF NOT ( @CONC >= @MAXCONC )
        BEGIN
            -- set additional rows esb to '0' to match @MAXCONC
            UPDATE TOP(@MAXCONC-@CONC) p2
            SET p2.esb = '0'
            FROM ( SELECT TOP(@MAXCONC-@CONC) p1.esb 
                   FROM SOA.dbo.photos_TEST  p1
                   WHERE  p1.esb = 'Q'
                   ORDER BY p1.arrivaldatetime ASC 
            ) p2

        END
    END
END

The solution had to be found in a complete different direction, i accidentaly defined my trigger as a after insert, update trigger instead of a after update trigger. The following trigger definition does work now

CREATE TRIGGER TR_PHOTO_AU
   ON       SOA.dbo.photos_TEST
   AFTER    UPDATE
AS 

DECLARE @MAXCONC INT  -- Maximum concurrent processes
DECLARE @CONC INT     -- Actual concurrent processes

SET @MAXCONC = 1      -- 1 concurrent processes

-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON

-- If column esb is involved in the update, does not necessarily mean
-- that the column itself is updated
If ( Update(ESB) )
BEGIN
    -- If column esb has been changed to 1 or Q
    IF ((SELECT esb FROM INSERTED) in ('1','Q'))
    BEGIN
        -- count the number of (imminent) active processes
        SET @CONC = (SELECT COUNT(*) 
                  FROM SOA.dbo.photos_TEST pc
                  WHERE pc.esb in ('0','R'))

        -- if maximum has not been reached
        IF NOT ( @CONC >= @MAXCONC )
        BEGIN
            -- set additional rows esb to '0' to match @MAXCONC
            UPDATE TOP(@MAXCONC-@CONC) p2
            SET p2.esb = '0'
            FROM ( SELECT TOP(@MAXCONC-@CONC) p1.esb 
                   FROM SOA.dbo.photos_TEST  p1
                   WHERE  p1.esb = 'Q'
                   ORDER BY p1.arrivaldatetime ASC 
            ) p2

        END
    END
END
Oo萌小芽oO 2024-10-05 10:40:45

你能试试这个吗?确保在 EXISTS 子句内的 WHERE 中将所有 PK 列指定为相等。

UPDATE  p1
SET     p1.esb = '0'
FROM    SOA.dbo.photos_TEST p1
WHERE   EXISTS ( SELECT TOP 5
                        *
                 FROM   SOA.dbo.photos_TEST p2
                 WHERE  p1.<KEYFIELD> = p2.<KEYFIELD>
                        AND p2.esb = 'Q'
                 ORDER BY p1.arrivaldatetime ASC )

Can you try this? Make sure to specify all you your PK columns as equal in the WHERE inside the EXISTS clause.

UPDATE  p1
SET     p1.esb = '0'
FROM    SOA.dbo.photos_TEST p1
WHERE   EXISTS ( SELECT TOP 5
                        *
                 FROM   SOA.dbo.photos_TEST p2
                 WHERE  p1.<KEYFIELD> = p2.<KEYFIELD>
                        AND p2.esb = 'Q'
                 ORDER BY p1.arrivaldatetime ASC )
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文