How to write a trigger that updates a table based on the action taken in another table?

时间:2016-08-31 18:11:31

标签: sql database triggers db2

I have a table named 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)
);

I need to create a new table named ORDERITEM_LOG that looks basically the same, but with two additional columns:

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

I need to make a trigger that watches the ORDERITEMS table. Whenever a row is inserted, deleted, or updated in the ORDERITEMS table, the identical operation needs to be done to the ORDERITEM_LOG table, with the additional two columns being populated with CURRENT TIMESTAMP, and a 'U', 'D', or 'I' (depending on the action taken), respectively.

For example, if I insert a row into the ORDERITEMS table, I would expect to see a duplicate row inserted into the ORDERITEM_LOG table, timestamped in LOG_ACTION_DATE, and an 'I' in the LOG_ACTION_TYPE. Then, if I were to delete the row in ORDERITEMS, I would expect to see the 'I' updated to a 'D' in the ORDERITEM_LOG table, and see the timestamp updated. I'm looking to have the ORDERITEM_LOG table updated before the ORDERITEMS table;

How do I write a trigger that would do what I'm looking for?

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:-1)

If I understand you want to snapshot your changes to table2. Good tactic by the time amount of data will create you a big headache. The sql code you need as below. You may create one trigger for all jobs with tag INSERT,DELETE,UPDATE or you may create seperate 3 triggers. Just pay attention that SQL UPDATE command triggers delete and insert statement in same time.

Below example is using BulkInsert and assume that you log tables exists. If you are updating a few rows at a time there is no problem,but if you are manipulating so many rows at same time probably you will timeout or have so long response time. To prevent that you may prefer to write same statement with where clause targeting primary key ( as where id=XXX) within a WHILE statement.

    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