如何编写一个触发器,根据在另一个表中采取的操作来更新一个表?

Posted

技术标签:

【中文标题】如何编写一个触发器,根据在另一个表中采取的操作来更新一个表?【英文标题】:How to write a trigger that updates a table based on the action taken in another table? 【发布时间】:2016-08-31 18:11:30 【问题描述】:

我有一个名为 ORDERITEMS 的表。

CREATE TABLE DB2ADMIN.ORDERITEMS (
  ORDERITEMS_ID BIGINT  NOT NULL,
  STOREENT_ID   INTEGER NOT NULL,
  ORDERS_ID BIGINT  NOT NULL,
  TERMCOND_ID   BIGINT,
  TRADING_ID    BIGINT,
  ITEMSPC_ID    BIGINT,
  CATENTRY_ID   BIGINT,
  PARTNUM   VARCHAR(64)
);

我需要创建一个名为ORDERITEM_LOG 的新表,它看起来基本相同,但多了两列:

CREATE TABLE DB2ADMIN.ORDERITEM_LOG (
  ORDERITEMS_ID BIGINT  NOT NULL,
  STOREENT_ID   INTEGER NOT NULL,
  ORDERS_ID BIGINT  NOT NULL,
  TERMCOND_ID   BIGINT,
  TRADING_ID    BIGINT,
  ITEMSPC_ID    BIGINT,
  CATENTRY_ID   BIGINT,
  PARTNUM   VARCHAR(64),
  LOG_ACTION_DATE VARCHAR(254),
  LOG_ACTION_TYPE VARCHAR(1)
);

我需要创建一个监视ORDERITEMS 表的触发器。每当在ORDERITEMS 表中插入、删除或更新一行时,都需要对ORDERITEM_LOG 表执行相同的操作,另外两列用CURRENT TIMESTAMP'U' 填充,@分别为 987654330@ 或 'I'(取决于所采取的操作)。

例如,如果我在ORDERITEMS 表中插入一行,我希望看到在ORDERITEM_LOG 表中插入一个重复的行,时间戳LOG_ACTION_DATE'I'LOG_ACTION_TYPE .然后,如果我要删除ORDERITEMS 中的行,我希望看到'I'ORDERITEM_LOG 表中更新为'D',并看到更新的时间戳。我希望在ORDERITEMS之前更新ORDERITEM_LOG 表;

如何编写一个触发器来满足我的需求?

【问题讨论】:

您看过手册中的触发器示例了吗?您是否尝试过编写一些代码?有什么特别令你苦恼的事情吗? 是的,我已经尝试编写一些仅用于插入的代码,但我不确定该去哪里。 CREATE TRIGGER OI_LOG_TRIGGER BEFORE INSERT ON ORDERITEMS FOR EACH FOR BEGIN ???插入 ORDERITEM_LOG () 值 ();??? --不确定这里发生了什么 END 【参考方案1】:

触发器类型 有两种类型的触发器。在触发器之后和而不是触发器。你必须使用 After 触发器

1)触发后

这些触发器在执行插入、更新或删除等操作后执行。

你必须使用下面的触发器

插入后

CREATE TRIGGER [dbo].[Customer_INSERT]
   ON [dbo].[Customers]
   AFTER INSERT
AS
BEGIN
   SET NOCOUNT ON;
   DECLARE @OrderItemsID;
  DECLARE @StroreentID;
   DECLARE @OrdersID;
   DECLARE @TermCondID;
   DECLARE @TradingID ;
   DECLARE @ItemSPCID;
   DECLARE @CatentryID;
   DECLARE @Partnum;  
   DECLARE @SysDateTime datetime = SYSDATETIME();
   DECLARE @LogActionType VARCHAR(1);

   SELECT @OrderItemsID = INSERTED.ORDERITEMS_ID;
   SELECT @StroreentID = INSERTED.STOREENT_ID;
   SELECT @OrdersID = INSERTED.ORDERS_ID;
   SELECT @TermCondID = INSERTED.TERMCOND_ID;
   SELECT @TradingID = INSERTED.TRADING_ID;
   SELECT @ItemSPCID = INSERTED.ITEMSPC_ID;
   SELECT @CatentryID = INSERTED.CATENTRY_ID;
   SELECT @Partnum = INSERTED.PARTNUM;

   @LogActionType = "1";

   FROM INSERTED

   INSERT INTO ORDERITEM_LOG
   VALUES (@OrderItemsID, @StroreentID, @OrdersID, @TermCondID, @TradingID, @ItemSPCID, @CatentryID, Partnum, LogActionType, @LogActionType)
END

更新后

 CREATE TRIGGER [dbo].[Customer_INSERT]
   ON [dbo].[Customers]
   AFTER UPDATE
AS
BEGIN
   SET NOCOUNT ON;
   DECLARE @OrderItemsID;
  DECLARE @StroreentID;
   DECLARE @OrdersID;
   DECLARE @TermCondID;
   DECLARE @TradingID ;
   DECLARE @ItemSPCID;
   DECLARE @CatentryID;
   DECLARE @Partnum;  
   DECLARE @SysDateTime datetime = SYSDATETIME();
   DECLARE @LogActionType VARCHAR(1);

   SELECT @OrderItemsID = INSERTED.ORDERITEMS_ID;
   SELECT @StroreentID = INSERTED.STOREENT_ID;
   SELECT @OrdersID = INSERTED.ORDERS_ID;
   SELECT @TermCondID = INSERTED.TERMCOND_ID;
   SELECT @TradingID = INSERTED.TRADING_ID;
   SELECT @ItemSPCID = INSERTED.ITEMSPC_ID;
   SELECT @CatentryID = INSERTED.CATENTRY_ID;
   SELECT @Partnum = INSERTED.PARTNUM;

   @LogActionType = "1";

   FROM INSERTED

   INSERT INTO ORDERITEM_LOG
   VALUES(@OrderItemsID, @StroreentID,@OrdersID,@TermCondID,@TradingID,@ItemSPCID,@CatentryID,Partnum,LogActionType, @LogActionType)
END

删除后

 CREATE TRIGGER [dbo].[Customer_INSERT]
   ON [dbo].[Customers]
   AFTER UPDATE
AS
BEGIN
   SET NOCOUNT ON;
   DECLARE @OrderItemsID;
   DECLARE @StroreentID;
   DECLARE @OrdersID;
   DECLARE @TermCondID;
   DECLARE @TradingID ;
   DECLARE @ItemSPCID;
   DECLARE @CatentryID;
   DECLARE @Partnum;  
   DECLARE @SysDateTime datetime = SYSDATETIME();
   DECLARE @LogActionType VARCHAR(1);

   SET @LogActionType = "1";
   SELECT @OrderItemsID = DELETED.ORDERITEMS_ID;
   SELECT @StroreentID = DELETED.STOREENT_ID;
   SELECT @OrdersID = DELETED.ORDERS_ID;
   SELECT @TermCondID = DELETED.TERMCOND_ID;
   SELECT @TradingID = DELETED.TRADING_ID;
   SELECT @ItemSPCID = DELETED.ITEMSPC_ID;
   SELECT @CatentryID = DELETED.CATENTRY_ID;
   SELECT @Partnum = DELETED.PARTNUM;


   INSERT INTO ORDERITEM_LOG
   VALUES(@OrderItemsID, @StroreentID,@OrdersID,@TermCondID,@TradingID,@ItemSPCID,@CatentryID,Partnum,LogActionType, @LogActionType)
END

【讨论】:

【参考方案2】:

如果我了解您想要将您的更改快照到 table2。时间数据量的好策略会让你头疼。您需要的sql代码如下。您可以为所有带有标签 INSERT、DELETE、UPDATE 的作业创建一个触发器,或者您可以创建单独的 3 个触发器。请注意 SQL UPDATE 命令同时触发删除和插入语句。

以下示例使用 BulkInsert 并假设您记录的表存在。如果您一次更新几行没有问题,但如果您同时操作这么多行,您可能会超时或响应时间过长。为防止出现这种情况,您可能更愿意在 WHILE 语句中使用 where 子句针对主键(如 where id=XXX)编写相同的语句。

    CREATE TRIGGER [ORDERITEMTRIGGER] ON [ORDERITEMS] 
FOR INSERT, UPDATE, DELETE 
AS
-- INSERT
set nocount on
insert into ORDERITEM_LOG(
  ORDERITEMS_ID,
  STOREENT_ID,
  ORDERS_ID,
  TERMCOND_ID,
  TRADING_ID,
  ITEMSPC_ID,
  CATENTRY_ID,
  PARTNUM,
  LOG_ACTION_DATE,
  LOG_ACTION_TYPE)
select   ORDERITEMS_ID,
  STOREENT_ID,
  ORDERS_ID,
  TERMCOND_ID,
  TRADING_ID,
  ITEMSPC_ID,
  CATENTRY_ID,
  PARTNUM,
  getdate(),'I' from inserted

-- DELETE (this triggers on delete and update because sql update has 2 phase delete and insert)
insert into ORDERITEM_LOG(
  ORDERITEMS_ID,
  STOREENT_ID,
  ORDERS_ID,
  TERMCOND_ID,
  TRADING_ID,
  ITEMSPC_ID,
  CATENTRY_ID,
  PARTNUM,
  LOG_ACTION_DATE,
  LOG_ACTION_TYPE)
select   ORDERITEMS_ID,
  STOREENT_ID,
  ORDERS_ID,
  TERMCOND_ID,
  TRADING_ID,
  ITEMSPC_ID,
  CATENTRY_ID,
  PARTNUM,
  getdate(),'D' from deleted

-- UPDATE
set nocount on
insert into ORDERITEM_LOG(
  ORDERITEMS_ID,
  STOREENT_ID,
  ORDERS_ID,
  TERMCOND_ID,
  TRADING_ID,
  ITEMSPC_ID,
  CATENTRY_ID,
  PARTNUM,
  LOG_ACTION_DATE,
  LOG_ACTION_TYPE)
select   ORDERITEMS_ID,
  STOREENT_ID,
  ORDERS_ID,
  TERMCOND_ID,
  TRADING_ID,
  ITEMSPC_ID,
  CATENTRY_ID,
  PARTNUM,
  getdate(),'U' from inserted
set nocount off

【讨论】:

以上是关于如何编写一个触发器,根据在另一个表中采取的操作来更新一个表?的主要内容,如果未能解决你的问题,请参考以下文章

如何编写一个触发器来检查一个值是不是已经在表中?

Swift 4:按钮在另一个 UITableViewCell 中触发相同的操作

如何捕获从 MYSQL 触发器(嵌入在另一个 py 脚本中)内部调用的 python 脚本的输出?

在另一个事实表中使用退化维度

在 PostgreSQL 中使用 executemany() 在另一个表中插入外键

如何根据laravel控制器中另一个表中保存的数据创建触发器以填充数据库中的表