触发器插入带有原始表的内部联接

问题描述 投票:0回答:1

我正在SQL文档中审查在SQL Server中创建DML触发器:Use the inserted and deleted Tables

有一个执行以下操作的示例:

以下示例创建DML触发器。尝试将新的采购订单插入PurchaseOrderHeader表时,此触发器检查以确保供应商的信用等级良好。要获得与刚刚插入的采购订单相对应的卖方的信用等级,必须参考“卖方”表并将其与插入的表合并。如果信用等级太低,则会显示一条消息,并且不会执行插入操作。

请注意,此示例不允许多行数据修改。

USE AdventureWorks2012;
GO

IF OBJECT_ID ('Purchasing.LowCredit','TR') IS NOT NULL
   DROP TRIGGER Purchasing.LowCredit;
GO

-- This trigger prevents a row from being inserted in the Purchasing.PurchaseOrderHeader table
-- when the credit rating of the specified vendor is set to 5 (below average).

CREATE TRIGGER Purchasing.LowCredit 
ON Purchasing.PurchaseOrderHeader
AFTER INSERT
AS
    IF EXISTS (SELECT *
               FROM Purchasing.PurchaseOrderHeader p 
               JOIN inserted AS i ON p.PurchaseOrderID = i.PurchaseOrderID 
               JOIN Purchasing.Vendor AS v ON v.BusinessEntityID = p.VendorID
               WHERE v.CreditRating = 5)
    BEGIN
        RAISERROR ('A vendor''s credit rating is too low to accept new purchase orders.', 16, 1);
        ROLLBACK TRANSACTION;
        RETURN 
    END;
GO

我不知道为什么示例内部将inserted表与Purchasing.PurchaseOrderHeader表连接在一起,然后又将vendor表连接在一起。

我是否可以仅使用inserted表直接加入供应商表而不与Purchasing.PurchaseOrderHeader表结合而获得相同的结果?

sql-server tsql database-trigger
1个回答
0
投票

不仅我相信您是正确的,而且我认为此文档页面上还有进一步的错误-根据我的经验,我不得不承认这种情况很少见。

以这部分为例:

请注意,此示例不允许多行数据修改。

这是一个错误的主张。触发代码示例将处理多行插入以及单行插入。

请注意,根据记录的(和观察到的)行为,插入的表将包含插入(或更新)到触发器的目标表的所有行:

插入的表在INSERT和UPDATE语句期间存储受影响的行的副本。在插入或更新事务期间,新行将同时添加到插入表和触发器表中。插入的表中的行是触发器表中新行的副本。

因此,在这种情况下,对inserted的联接应足以执行所讨论的业务规则。

话虽这么说,使用触发器来强制执行业务规则可能会变得困难甚至有问题-请注意,此触发器仅覆盖插入的行,而不覆盖更新的行。这意味着可能会插入带有有效值的新行,然后再更新为无效值。

© www.soinside.com 2019 - 2024. All rights reserved.