ORACLE PL/SQL 触发器使用两个不同的表

Posted

技术标签:

【中文标题】ORACLE PL/SQL 触发器使用两个不同的表【英文标题】:ORACL PL/SQL Trigger Using Two different tables 【发布时间】:2017-09-29 12:20:23 【问题描述】:

除了编写迁移 SQL 和一些基本触发器之外,我对 PL/SQL 主题的经验并不多。因此,我会直接问我的问题,以便在我期望的表的触发器中至少有一个起点。

我们有以下表格:

VIB: Varchar
Locale: Varchar
Status : Varchar
Released : boolean

我需要D2C_EVENT_GENERATION_MASTER 表上的触发器,要求是,某些系统会在此表中插入“vib”列没有 vib 的 LOCALE 值 .所以我们的期望是在该系统的插入操作之前计算语言环境(从 release_table 中找到合适的语言环境),通过向RELEASE_TABLE 询问该VIB 存在的适当语言环境,并且发布标志为“真”。

CREATE OR REPLACE TRIGGER BL_D2C_EVENT_GENERATION_MASTER
   BEFORE INSERT
   ON D2C_EVENT_GENERATION_MASTER
   FOR EACH ROW
DECLARE
   l_locale  varchar2(100);
BEGIN
    if :NEW.locale is null then
    for rec in (select locale from RELEASE_TABLE@pdpe.mch.bshg.com where vib=:NEW.vib AND released = 1)
    loop
    INSERT INTO d2c_event_generation_master (vib,locale) VALUES (:NEW.vib,rec.locale);
    end loop;
    DELETE FROM d2c_event_generation_master where vib=:NEW.vib AND locale is null;
    end if;
END;

我即将创建此触发器,但只发生了一个我无法修复的异常。当我在这样的表中插入具有空区域设置值的行时:

  INSERT INTO D2C_EVENT_GENERATION_AP (vib) values ('GP200046');

它从其他表中获取语言环境,但插入三行:

GP200046    fr-BE
GP200046    nl-BE
GP200046    null

我不想在这里看到“null”,我尝试了一些立即执行或其他一些人员,但找不到任何东西。

你能帮忙吗?

【问题讨论】:

你对 LOCALE 做了什么样的计算?您是否从另一个表中检索数据的数学计算? 想象一下,这只是一个类似“select vib from release_table where released = true”的查询,对于响应语言环境,我应该使用这些语言环境创建插入或更新到其他表。 因此,如果我理解正确,有人将只插入没有语言环境的主键 D2C_EVENT_GENERATION_MASTER 表,然后您需要查询 RELEASE 表以获取使用 VIB 列连接两个表的语言环境值,对吗? ? 没错!发布表将为我提供必要的语言环境,这些表可以使用 VIB 列轻松连接。 好的,那么触发器是要走的路,对于第二个触发器,您希望首先比具有 VIB 和区域设置的行不存在于状态不同的表中 NEW,如果是这种情况,那么您只需将状态更新为 NEW? 【参考方案1】:

这是插入前的触发器,用于从发布表中获取值:

CREATE OR REPLACE TRIGGER BI_D2C_EVENT_GENERATION_MASTER
   BEFORE INSERT
   ON D2C_EVENT_GENERATION_MASTER
   FOR EACH ROW
DECLARE
   l_locale   varchar2(100);
BEGIN
    if :NEW.locale is null then
        select locale INTO l_locale from release where vib=:NEW.vib;
        :NEW.locale := l_locale;
    end if;
END;
/

编辑:

对于第二种解决方案,我建议创建一个程序:

CREATE OR REPLACE PROCEDURE MI_D2C_EVENT_GENERATION_MASTER (p_vib number, p_locale varchar2)
IS
 l_vib number := p_vib;
 l_locale varchar2(100) := p_locale;
BEGIN   
    MERGE INTO D2C_EVENT_GENERATION_MASTER event
    USING (SELECT vib, locale from D2C_EVENT_GENERATION_MASTER) old_event
    ON (event.vib = l_vib
        and event.locale = l_locale)
    WHEN MATCHED THEN
        UPDATE SET event.STATUS = 'NEW'
        WHERE event.STATUS != 'NEW'
    WHEN NOT MATCHED THEN 
        INSERT (vib,locale,status) VALUES (l_vib, l_locale, 'STATUS')';
END;
/

【讨论】:

为什么选择动态 SQL? @WilliamRobertson 你说得对,没必要,我更新了答案。 触发器仍然是动态的。 大家好,如果可能的话,你能检查我的编辑吗?关于从表中删除空值?答案也没有涵盖多行条件,我编辑了循环以在我的问题上使用它。

以上是关于ORACLE PL/SQL 触发器使用两个不同的表的主要内容,如果未能解决你的问题,请参考以下文章

Oracle 12 PL/SQL 在触发器中检索存储过程名称

如何使用间隔 1 分钟在两个日期之间将时间序列数据生成到 Oracle PL/SQL 中的表中?

如何使用触发器在同一张表中插入新行(Oracle PL/SQL 10G)?

“如何修复 oracle pl/sql 中的触发器?

oracle学习-PL SQL 存储过程中循环触发器

pl/sql 存储过程从日期等于存储过程参数的表中进行选择