如何编写一个触发器,根据在另一个表中采取的操作来更新一个表?
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 脚本的输出?