【问题标题】:How to make a Trigger on Master-Detail如何在主从细节上触发
【发布时间】:2016-12-09 06:09:51
【问题描述】:

我有以下情况:

CREATE TABLE dbo.Orders
(  
    OrderID int IDENTITY (1,1) NOT NULL  
  , OrderVersion int DEFAULT(1)
  , Customer varchar(30)
  , ScheduleDate date
  , PaymentOption int
);  

CREATE TABLE dbo.OrdersItems
(  
    OrderItemsID int IDENTITY (1,1) NOT NULL  
  , OrderID  int
  , Product  varchar(100)
  , Qty      int 
  , value    decimal(18,2)
);  

CREATE TABLE dbo.logOrders
(  
    OrderID int NOT NULL  
  , OrderVersion int DEFAULT(1)
  , Customer varchar(30)
  , ScheduleDate date
  , PaymentOption int
);  

CREATE TABLE dbo.logOrdersItems
(  
    OrderItemsID int NOT NULL  
  , OrderID  int
  , Product  varchar(100)
  , Qty      int 
  , value    decimal(18,2)
); 

-- Insert values into the table.  
INSERT INTO dbo.Orders (Customer , ScheduleDate, PaymentOption)  
VALUES ('John', 2016-09-01, 1);  

INSERT INTO dbo.OrdersItems( OrderId, Product, Qty, Value)
VALUES (1, 'Foo', 20, 35.658), 
       (1, 'Bla', 50, 100)
       (1, 'XYZ', 10, 3589)

第一句话

UPDATE Orders set ScheduleDate = 2016-10-05 WHERE OrderId = 1

第二个陈述

Delete From OrdersItems WHERE OrderItemsID = 2
UPDATE OrdersItems set Qty = 5 WHERE OrderItemsID = 1

第三条语句

Update Orders set PaymentOption = 2 WHERE OrderId = 1
Update OrdersItems set Value = 1050 WHERE OrderItemsID = 3

我试图弄清楚如何在上面的每个语句示例之后在日志表上插入更改之前的数据。并在表 Orders 上将 OrderVersion 设置为 OrderVersion + 1。 因此,在日志表上,我将拥有后一个版本之后的所有版本。

是否可以在 UPDATE、DELETE、INSERT 语句之前创建一个触发器来监视两个表并执行获取原始数据以获取原始数据并在 logTables 上插入?

这里有一个示例来更好地解释我想要的结果。

This is the Initial Data on table Orders and OrdersItems

如果我对订单(任何列)进行更新或对 OrdersItems 进行更新、插入、删除,我需要分别在 logTables 上插入图像上的数据。 有了这个,我将在 logOrders 和 logItems 上获得原始数据,在 Orders 和 Items 上获得更改后的数据。

我希望我能更好地解释我的意思。

【问题讨论】:

  • 您可以通过触发器实现您想要的(在日志中插入更改前的数据表),但是您的要求还不够清楚,请您用一些示例进行解释并一起解释,包括预期结果
  • 只能为单个表指定 dml 触发器。但是,您可以为将处理更新、删除和插入的每个表创建一个触发器。

标签: sql-server tsql sql-server-2014 database-trigger


【解决方案1】:

您将需要两个触发器。 Orders 表的触发器处理 Orders 表的更新/删除。 OrdersItems 表的触发器对 OrdersItems 执行相同的操作。触发器如下所示:

对于订单表:

CREATE TRIGGER dbo.Orders_trigger 
   ON  dbo.Orders 
   AFTER DELETE,UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    INSERT INTO dbo.logOrders
    SELECT * FROM DELETED;

    INSERT INTO dbo.logOrdersItems
    SELECT oi.* FROM OrdersItems oi
    WHERE oi.OrderID IN (SELECT OrderId FROM DELETED);

END
GO

对于 OrdersItems:

CREATE TRIGGER dbo.OrdersItems_trigger 
   ON  dbo.OrdersItems 
   AFTER DELETE,UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    --Inerst the changed/deleted OrdersItems into the log
    INSERT INTO dbo.logOrdersItems
    SELECT * FROM DELETED

    --Inserts the unchanged sibling OrdersItems records into the log
    INSERT INTO dbo.logOrdersItems
    SELECT oi.* FROM OrdersItems oi
    WHERE oi.OrderId IN (SELECT DISTINCT OrderId FROM DELETED)
    AND oi.OrderItemsID NOT IN (SELECT DISTINCT OrderItemsID FROM DELETED);

    INSERT INTO dbo.logOrders
    SELECT o.* FROM Orders o
    WHERE o.OrderID IN (SELECT DISTINCT OrderId FROM DELETED);

END
GO

订单触发器相当简单。使用虚拟 DELETED 表将原始版本的记录插入到日志中。然后加入子 OrdersItems 记录并将它们也插入到日志中。这种写法,即使您一次更新或删除多个订单记录,它也可以工作。

OrdersItems 触发器有点复杂。您需要记录 OrdersItems 和 Orders Records 的预更改版本。但是您还希望(我认为)记录未更改的“兄弟”OrdersItems 记录,以便您对记录有完整的了解。

我知道这只是您的示例数据,但您需要在日志表中的记录中添加某种时间戳。否则你只会得到一堆重复的行,你无法分辨哪个是哪个。在触发器开始时,您可以创建一个变量来保存更新日期时间,然后将其附加到日志的 INSERT 语句中。

DECLARE @UpdateDateTime DATETIME;
SET @UpdateDateTime = GETUTCDATE();

【讨论】:

  • @JeanSilvaPaulo 刚转回来。这解决了您的问题吗?
猜你喜欢
  • 2013-08-25
  • 1970-01-01
  • 1970-01-01
  • 2019-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多