使用触发器插入/更新到另一个表
Posted
技术标签:
【中文标题】使用触发器插入/更新到另一个表【英文标题】:Insert/Update to another table using trigger 【发布时间】:2014-05-27 06:38:19 【问题描述】:我有 2 个表,tableA 和 tableB。
tableA:
id | status | Flag | ResultOfAction | ExternalId | Customer
1 200 2 0 332 C1
2 200 0 0 333 C1
如果 old.status new.status OR Flag = 3 OR ResultofAction = 1,触发器将填充另一个表。
例如
tableB:
id | status | Flag | ResultOfAction | ExternalId | tableAId
1 200 2 0 332 1
如果 tableA 有新的插入:
tableA:
id | status | Flag | ResultOfAction | ExternalId | Customer
1 200 2 0 332 C1
2 200 0 0 333 C1
3 200 2 0 334 C1
TableB 将自动填充新行。
tableB:
id | status | Flag | ResultOfAction | ExternalId | tableAId
1 200 2 0 332 1
2 200 2 0 334 3
如果 tableA 中的一行更新。例如id 为 1 到 300,然后是 tableB
tableB:
id | status | Flag | ResultOfAction | ExternalId | tableAId
1 300 2 0 332 1
2 200 2 0 334 3
这是我现有的触发器。有人可以帮忙吗?
CREATE OR REPLACE TRIGGER TABLEA_TRG AFTER INSERT OR UPDATE ON TABLEA
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW WHEN (OLD.STATUS <> NEW.STATUS OR NEW.FLAG = 3 or NEW.RESULTOFACTION = 1)
BEGIN
IF INSERTING THEN
INSERT INTO TABLEB(TABLEAID, ExternalId, STATUS, Flag)
SELECT :NEW.ID, :NEW.ExternalId, :NEW.STATUS, :NEW.FLAG FROM DUAL
WHEN NOT EXISTS (SELECT 1 FROM TABLEB WHERE tableAId = :NEW.id);
ELSIF UPDATING THEN
IF :NEW.STATUS <> :OLD.STATUS THEN
UPDATE TABLEB DWT SET DWT.tableAId = :NEW.id, DWT.ExternalId = :NEW.ExternalId,
DWT.STATUS = :NEW.STATUS, DWT.Flag = :NEW.Flag;
END IF;
MERGE INTO TABLEB D
USING DUAL ON (D.TABLEAID = :NEW.ID)
WHEN MATCHED THEN
UPDATE SET D.STATUS = :NEW.STATUS
WHEN NOT MATCHED THEN
INSERT (D.TABLEAID, D.ExternalId, D.STATUS, D.FLAG) VALUE (:NEW.ID, :NEW.ExternalId, :NEW.STATUS, :NEW.FLAG);
END IF;
END;
/
有错误 * 错误(7,7): PL/SQL: SQL 语句被忽略 * 错误(9,16): PL/SQL: ORA-00933: SQL 命令未正确结束
这是我第一次在 Oracle 中做触发器,有人可以帮帮我吗?
【问题讨论】:
如果 TableA 正在插入,则编写插入语句,否则编写更新语句。这有什么难的? @APC,第一次,不太了解触发器的语法。在网上找到那些源代码。 【参考方案1】:看看这个:
CREATE OR REPLACE TRIGGER TABLEA_TRG AFTER INSERT OR UPDATE ON TABLEA
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW WHEN (OLD.STATUS <> NEW.STATUS OR NEW.FLAG = 3 or NEW.RESULTOFACTION
begin
IF INSERTING THEN
begin
INSERT INTO TABLEB
(TABLEAID, ExternalId, STATUS, Flag) values
(:new.id, :new.externalId, :new.status, :new.flag);
-- assuming, there is an unique key on id
exception
when dup_val_on_index then
null;
end;
ELSIF UPDATING THEN
IF :NEW.STATUS <> :OLD.STATUS THEN
UPDATE TABLEB DWT
SET DWT.tableAId = :NEW.id,
DWT.ExternalId = :NEW.ExternalId,
DWT.STATUS = :NEW.STATUS,
DWT.Flag = :NEW.Flag;
END IF;
MERGE INTO TABLEB D
USING DUAL
ON (D.TABLEAID = :NEW.ID)
WHEN MATCHED THEN
UPDATE SET D.STATUS = :NEW.STATUS
WHEN NOT MATCHED THEN
INSERT
(D.TABLEAID, D.ExternalId, D.STATUS, D.FLAG) VALUEs
(:NEW.ID, :NEW.ExternalId, :NEW.STATUS, :NEW.FLAG);
END IF;
end test;
【讨论】:
【参考方案2】:我真的没有问题,但这里有一个例子:
我有一个 TABLE_A 和一个审计表 (TABLE_A_AUDIT),其中包含对 TABLE_A 的所有操作。 因此我有三个触发器,一个用于插入,一个用于更新,一个用于删除。
create table TABLE_A
(
key_value VARCHAR2(20),
value VARCHAR2(20)
)
create table TABLE_A_AUDIT
(
audit_timestamp TIMESTAMP(6),
audit_action VARCHAR2(1),
key_value VARCHAR2(20),
value VARCHAR2(20)
)
插入触发器:
create or replace trigger table_a_insert before insert on table_a for each row
begin
insert into table_a_audit
(audit_timestamp, audit_action, key_value, value)
values
(systimestamp, 'I', :new.key_value, :new.value);
end;
更新触发器:
create or replace trigger table_a_update before update on table_a for each row
begin
insert into table_a_audit
(audit_timestamp, audit_action, key_value, value)
values
(systimestamp, 'U', :new.key_value, :new.value);
end;
删除触发器:
create or replace trigger table_a_delete before delete on table_a for each row
begin
insert into table_a_audit
(audit_timestamp, audit_action, key_value, value)
values
(systimestamp, 'D', :old.key_value, :old.value);
end;
我希望这个例子有所帮助。
【讨论】:
【参考方案3】:您不能从 DUAL 表中选择 :new.id 等。该表只有“DUMMY”列。 我不确定你想要什么,但我认为你应该使用序列来获取新 ID ...
【讨论】:
【参考方案4】:USE [SocRamala]
GO
/****** Object: Trigger [dbo].[tgr_LOGMILLPUR] Script Date: 8/1/2018 1:56:55 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER trigger [dbo].[tgr_LOGMILLPUR] on [dbo].[MILL_PUR]
after UPDATE, INSERT, DELETE
as
if exists(SELECT * from inserted) and exists (SELECT * from deleted)
begin
INSERT into LOG_MILLPUR(M_NUMBER, M_DATE, M_CENTRE, M_Alt_Cen, M_SOC, M_MODE, M_VILL, M_GROW, M_CATEG, M_VAR, M_GROSS, M_TARE, M_JOONA, M_FinalWt, M_AMOUNT, M_SMP_AMT, M_ADDI_AMT, M_CounterNo, M_GrossSlipNo, M_BillNo, M_HologramNo, M_TROLLYNO, M_CANE_TYPE, M_CANE_QUAL, M_SH_SUP_Wt, M_EXC_SUP_Wt, M_PAY_LOCK, M_Pay_Lock_Dt, M_Pay_Lock_opr, M_TOK_NO, M_TOK_DT, M_TOK_TM, M_TOK_OPR, M_TOK_SHIFT, M_TOK_COUNTERNO, M_TOK_KANTANO, M_TOK_IMAGE, M_GROS_DT, M_GROS_OPR, M_GROS_SHIFT, M_GROS_COUNTERNO, M_GROS_FIMAGE, M_GROS_BIMAGE, M_CardNo, M_TARE_DT, M_TARE_OPR, M_SHIFT, M_IND_NO, M_IND_DT, M_IND_CN, M_W_CLERK, M_ADV_AMT, M_ADV_DT, M_SYS_DT, M_SYS_TM, M_CASHIER, M_SCROLL, m_adnl_amt, Token_no, M_REMARK, M_HHT, M_CENTRE_HHT, m_adv_Amt20, M_REMARK2, M_G_UNIQUE_NO,M_BILLA_NO, m_hologram_no, m_adv_paid, M_FImagName, M_BImagName, M_PAYABLE, M_BD_CD, M_PurDate, ID,M_reprint, M_cr_by, m_cr_date, LOG_STATUS, LOG_DATE,LOG_ACTIVITY, LOG_IP, LOG_SQLUSER, LOG_PCNAME)
Select M_NUMBER, M_DATE, M_CENTRE, M_Alt_Cen, M_SOC, M_MODE, M_VILL, M_GROW, M_CATEG, M_VAR, M_GROSS, M_TARE, M_JOONA, M_FinalWt, M_AMOUNT, M_SMP_AMT, M_ADDI_AMT, M_CounterNo, M_GrossSlipNo, M_BillNo, M_HologramNo, M_TROLLYNO, M_CANE_TYPE, M_CANE_QUAL, M_SH_SUP_Wt, M_EXC_SUP_Wt, M_PAY_LOCK, M_Pay_Lock_Dt, M_Pay_Lock_opr, M_TOK_NO, M_TOK_DT, M_TOK_TM, M_TOK_OPR, M_TOK_SHIFT, M_TOK_COUNTERNO, M_TOK_KANTANO, M_TOK_IMAGE, M_GROS_DT, M_GROS_OPR, M_GROS_SHIFT, M_GROS_COUNTERNO, M_GROS_FIMAGE, M_GROS_BIMAGE, M_CardNo, M_TARE_DT, M_TARE_OPR, M_SHIFT, M_IND_NO, M_IND_DT, M_IND_CN, M_W_CLERK, M_ADV_AMT, M_ADV_DT, M_SYS_DT, M_SYS_TM, M_CASHIER, M_SCROLL, m_adnl_amt, Token_no, M_REMARK, M_HHT, M_CENTRE_HHT, m_adv_Amt20, M_REMARK2, M_G_UNIQUE_NO, M_BILLA_NO, m_hologram_no, m_adv_paid, M_FImagName, M_BImagName, M_PAYABLE, M_BD_CD, M_PurDate, ID,M_reprint, M_cr_by, m_cr_date, 'NEW', GETDATE(), 'UPDATE',CONVERT(NVARCHAR,ISNULL(CONNECTIONPROPERTY('client_net_address'),'')),CONVERT(NVARCHAR,ISNULL(SUSER_SNAME(),'')),CONVERT(NVARCHAR,ISNULL(HOST_NAME(),'')) from inserted i ;
INSERT into LOG_MILLPUR(M_NUMBER, M_DATE, M_CENTRE, M_Alt_Cen, M_SOC, M_MODE, M_VILL, M_GROW, M_CATEG, M_VAR, M_GROSS, M_TARE, M_JOONA, M_FinalWt, M_AMOUNT, M_SMP_AMT, M_ADDI_AMT, M_CounterNo, M_GrossSlipNo, M_BillNo, M_HologramNo, M_TROLLYNO, M_CANE_TYPE, M_CANE_QUAL, M_SH_SUP_Wt, M_EXC_SUP_Wt, M_PAY_LOCK, M_Pay_Lock_Dt, M_Pay_Lock_opr, M_TOK_NO, M_TOK_DT, M_TOK_TM, M_TOK_OPR, M_TOK_SHIFT, M_TOK_COUNTERNO, M_TOK_KANTANO, M_TOK_IMAGE, M_GROS_DT, M_GROS_OPR, M_GROS_SHIFT, M_GROS_COUNTERNO, M_GROS_FIMAGE, M_GROS_BIMAGE, M_CardNo, M_TARE_DT, M_TARE_OPR, M_SHIFT, M_IND_NO, M_IND_DT, M_IND_CN, M_W_CLERK, M_ADV_AMT, M_ADV_DT, M_SYS_DT, M_SYS_TM, M_CASHIER, M_SCROLL, m_adnl_amt, Token_no, M_REMARK, M_HHT, M_CENTRE_HHT, m_adv_Amt20, M_REMARK2, M_G_UNIQUE_NO, M_BILLA_NO, m_hologram_no, m_adv_paid, M_FImagName, M_BImagName, M_PAYABLE, M_BD_CD, M_PurDate, ID,M_reprint, M_cr_by, m_cr_date, LOG_STATUS, LOG_DATE,LOG_ACTIVITY, LOG_IP, LOG_SQLUSER, LOG_PCNAME)
Select M_NUMBER, M_DATE, M_CENTRE, M_Alt_Cen, M_SOC, M_MODE, M_VILL, M_GROW, M_CATEG, M_VAR, M_GROSS, M_TARE, M_JOONA, M_FinalWt, M_AMOUNT, M_SMP_AMT, M_ADDI_AMT, M_CounterNo, M_GrossSlipNo, M_BillNo, M_HologramNo, M_TROLLYNO, M_CANE_TYPE, M_CANE_QUAL, M_SH_SUP_Wt, M_EXC_SUP_Wt, M_PAY_LOCK, M_Pay_Lock_Dt, M_Pay_Lock_opr, M_TOK_NO, M_TOK_DT, M_TOK_TM, M_TOK_OPR, M_TOK_SHIFT, M_TOK_COUNTERNO, M_TOK_KANTANO, M_TOK_IMAGE, M_GROS_DT, M_GROS_OPR, M_GROS_SHIFT, M_GROS_COUNTERNO, M_GROS_FIMAGE, M_GROS_BIMAGE, M_CardNo, M_TARE_DT, M_TARE_OPR, M_SHIFT, M_IND_NO, M_IND_DT, M_IND_CN, M_W_CLERK, M_ADV_AMT, M_ADV_DT, M_SYS_DT, M_SYS_TM, M_CASHIER, M_SCROLL, m_adnl_amt, Token_no, M_REMARK, M_HHT, M_CENTRE_HHT, m_adv_Amt20, M_REMARK2, M_G_UNIQUE_NO, M_BILLA_NO, m_hologram_no, m_adv_paid, M_FImagName, M_BImagName, M_PAYABLE, M_BD_CD, M_PurDate, ID,M_reprint, M_cr_by, m_cr_date, 'OLD', GETDATE(), 'UPDATE',CONVERT(NVARCHAR,ISNULL(CONNECTIONPROPERTY('client_net_address'),'')),CONVERT(NVARCHAR,ISNULL(SUSER_SNAME(),'')),CONVERT(NVARCHAR,ISNULL(HOST_NAME(),'')) from deleted D ;
end
If exists (Select * from inserted) and not exists(Select * from deleted)
begin
INSERT into LOG_MILLPUR(M_NUMBER, M_DATE, M_CENTRE, M_Alt_Cen, M_SOC, M_MODE, M_VILL, M_GROW, M_CATEG, M_VAR, M_GROSS, M_TARE, M_JOONA, M_FinalWt, M_AMOUNT, M_SMP_AMT, M_ADDI_AMT, M_CounterNo, M_GrossSlipNo, M_BillNo, M_HologramNo, M_TROLLYNO, M_CANE_TYPE, M_CANE_QUAL, M_SH_SUP_Wt, M_EXC_SUP_Wt, M_PAY_LOCK, M_Pay_Lock_Dt, M_Pay_Lock_opr, M_TOK_NO, M_TOK_DT, M_TOK_TM, M_TOK_OPR, M_TOK_SHIFT, M_TOK_COUNTERNO, M_TOK_KANTANO, M_TOK_IMAGE, M_GROS_DT, M_GROS_OPR, M_GROS_SHIFT, M_GROS_COUNTERNO, M_GROS_FIMAGE, M_GROS_BIMAGE, M_CardNo, M_TARE_DT, M_TARE_OPR, M_SHIFT, M_IND_NO, M_IND_DT, M_IND_CN, M_W_CLERK, M_ADV_AMT, M_ADV_DT, M_SYS_DT, M_SYS_TM, M_CASHIER, M_SCROLL, m_adnl_amt, Token_no, M_REMARK, M_HHT, M_CENTRE_HHT, m_adv_Amt20, M_REMARK2, M_G_UNIQUE_NO, M_BILLA_NO, m_hologram_no, m_adv_paid, M_FImagName, M_BImagName, M_PAYABLE, M_BD_CD, M_PurDate, ID,M_reprint, M_cr_by, m_cr_date, LOG_STATUS, LOG_DATE, LOG_ACTIVITY, LOG_IP, LOG_SQLUSER, LOG_PCNAME)
Select M_NUMBER, M_DATE, M_CENTRE, M_Alt_Cen, M_SOC, M_MODE, M_VILL, M_GROW, M_CATEG, M_VAR, M_GROSS, M_TARE, M_JOONA, M_FinalWt, M_AMOUNT, M_SMP_AMT, M_ADDI_AMT, M_CounterNo, M_GrossSlipNo, M_BillNo, M_HologramNo, M_TROLLYNO, M_CANE_TYPE, M_CANE_QUAL, M_SH_SUP_Wt, M_EXC_SUP_Wt, M_PAY_LOCK, M_Pay_Lock_Dt, M_Pay_Lock_opr, M_TOK_NO, M_TOK_DT, M_TOK_TM, M_TOK_OPR, M_TOK_SHIFT, M_TOK_COUNTERNO, M_TOK_KANTANO, M_TOK_IMAGE, M_GROS_DT, M_GROS_OPR, M_GROS_SHIFT, M_GROS_COUNTERNO, M_GROS_FIMAGE, M_GROS_BIMAGE, M_CardNo, M_TARE_DT, M_TARE_OPR, M_SHIFT, M_IND_NO, M_IND_DT, M_IND_CN, M_W_CLERK, M_ADV_AMT, M_ADV_DT, M_SYS_DT, M_SYS_TM, M_CASHIER, M_SCROLL, m_adnl_amt, Token_no, M_REMARK, M_HHT, M_CENTRE_HHT, m_adv_Amt20, M_REMARK2, M_G_UNIQUE_NO, M_BILLA_NO, m_hologram_no, m_adv_paid, M_FImagName, M_BImagName, M_PAYABLE, M_BD_CD, M_PurDate, ID,M_reprint, M_cr_by, m_cr_date, 'NEW', GETDATE(), 'INSERT',CONVERT(NVARCHAR,ISNULL(CONNECTIONPROPERTY('client_net_address'),'')),CONVERT(NVARCHAR,ISNULL(SUSER_SNAME(),'')),CONVERT(NVARCHAR,ISNULL(HOST_NAME(),'')) from inserted i ;
end
If exists(select * from deleted) and not exists(Select * from inserted)
begin
INSERT into LOG_MILLPUR(M_NUMBER, M_DATE, M_CENTRE, M_Alt_Cen, M_SOC, M_MODE, M_VILL, M_GROW, M_CATEG, M_VAR, M_GROSS, M_TARE, M_JOONA, M_FinalWt, M_AMOUNT, M_SMP_AMT, M_ADDI_AMT, M_CounterNo, M_GrossSlipNo, M_BillNo, M_HologramNo, M_TROLLYNO, M_CANE_TYPE, M_CANE_QUAL, M_SH_SUP_Wt, M_EXC_SUP_Wt, M_PAY_LOCK, M_Pay_Lock_Dt, M_Pay_Lock_opr, M_TOK_NO, M_TOK_DT, M_TOK_TM, M_TOK_OPR, M_TOK_SHIFT, M_TOK_COUNTERNO, M_TOK_KANTANO, M_TOK_IMAGE, M_GROS_DT, M_GROS_OPR, M_GROS_SHIFT, M_GROS_COUNTERNO, M_GROS_FIMAGE, M_GROS_BIMAGE, M_CardNo, M_TARE_DT, M_TARE_OPR, M_SHIFT, M_IND_NO, M_IND_DT, M_IND_CN, M_W_CLERK, M_ADV_AMT, M_ADV_DT, M_SYS_DT, M_SYS_TM, M_CASHIER, M_SCROLL, m_adnl_amt, Token_no, M_REMARK, M_HHT, M_CENTRE_HHT, m_adv_Amt20, M_REMARK2, M_G_UNIQUE_NO, M_BILLA_NO, m_hologram_no, m_adv_paid, M_FImagName, M_BImagName, M_PAYABLE, M_BD_CD, M_PurDate, ID,M_reprint, M_cr_by, m_cr_date, LOG_STATUS, LOG_DATE, LOG_ACTIVITY, LOG_IP, LOG_SQLUSER, LOG_PCNAME)
Select M_NUMBER, M_DATE, M_CENTRE, M_Alt_Cen, M_SOC, M_MODE, M_VILL, M_GROW, M_CATEG, M_VAR, M_GROSS, M_TARE, M_JOONA, M_FinalWt, M_AMOUNT, M_SMP_AMT, M_ADDI_AMT, M_CounterNo, M_GrossSlipNo, M_BillNo, M_HologramNo, M_TROLLYNO, M_CANE_TYPE, M_CANE_QUAL, M_SH_SUP_Wt, M_EXC_SUP_Wt, M_PAY_LOCK, M_Pay_Lock_Dt, M_Pay_Lock_opr, M_TOK_NO, M_TOK_DT, M_TOK_TM, M_TOK_OPR, M_TOK_SHIFT, M_TOK_COUNTERNO, M_TOK_KANTANO, M_TOK_IMAGE, M_GROS_DT, M_GROS_OPR, M_GROS_SHIFT, M_GROS_COUNTERNO, M_GROS_FIMAGE, M_GROS_BIMAGE, M_CardNo, M_TARE_DT, M_TARE_OPR, M_SHIFT, M_IND_NO, M_IND_DT, M_IND_CN, M_W_CLERK, M_ADV_AMT, M_ADV_DT, M_SYS_DT, M_SYS_TM, M_CASHIER, M_SCROLL, m_adnl_amt, Token_no, M_REMARK, M_HHT, M_CENTRE_HHT, m_adv_Amt20, M_REMARK2, M_G_UNIQUE_NO, M_BILLA_NO, m_hologram_no, m_adv_paid, M_FImagName, M_BImagName, M_PAYABLE, M_BD_CD, M_PurDate, ID,M_reprint, M_cr_by, m_cr_date, 'OLD', GETDATE(), 'DELETE',CONVERT(NVARCHAR,ISNULL(CONNECTIONPROPERTY('client_net_address'),''))LOG_IP,CONVERT(NVARCHAR,ISNULL(SUSER_SNAME(),''))LOG_SQLUSER,CONVERT(NVARCHAR,ISNULL(HOST_NAME(),''))LOG_PCNAME from deleted D ;
end
通过仅更改此代码的插入和选择命令的列名来编写查询
【讨论】:
【参考方案5】:插入触发器:
create or replace trigger table_a_insert before insert on table_a for each row
begin
insert into table_a_audit
(audit_timestamp, audit_action, key_value, value)
values
(systimestamp, 'I', :new.key_value, :new.value);
end;
更新触发器:
create or replace trigger table_a_update before update on table_a for each row
begin
UPDATE table_a
set value=:new.value
WHERE table_a.key_value= :new.key_value;
end;
它在 Oracle 9i 和 12C 版本上完美运行。 (插入和更新触发器)。如有任何疑问,请告诉我们。
【讨论】:
以上是关于使用触发器插入/更新到另一个表的主要内容,如果未能解决你的问题,请参考以下文章