【问题标题】:Oracle Trigger to insert /update to another tableOracle触发器插入/更新到另一个表
【发布时间】:2019-04-02 03:23:16
【问题描述】:

基本上,我想创建一个 oracle 触发器,它将跟踪表中的插入/更新,我想每天将这些更改的记录单独插入到一个新表中。这个新表数据将用于我的每日数据刷新(更像是 CDC 方法)

我正在使用下面的代码。我的期望是当我的 CUSTOMER 表得到 INSERT/UPDATED 时,该记录应该在 CUSTOMER_D 表中可用。但我在下面的代码中遗漏了一些东西

CREATE OR REPLACE TRIGGER CUST_TRIG AFTER INSERT OR UPDATE ON CUSTOMERS
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW WHEN (OLD.ID <> NEW.ID)
begin
  IF INSERTING THEN
    begin
    INSERT INTO CUSTOMERS_D
      (ID, NAME, AGE, ADDRESS, SALARY) values
      (:new.ID, :new.NAME, :new.AGE, :new.ADDRESS, :new.SALARY);
    -- assuming, there is an unique key on id
    exception
      when dup_val_on_index then
        null;
    end;

  ELSIF UPDATING THEN
    IF :NEW.ID = :OLD.ID THEN
      UPDATE CUSTOMERS_D DWT
         SET DWT.ID = :NEW.ID,
             DWT.NAME = :NEW.NAME,
             DWT.AGE = :NEW.AGE,
             DWT.ADDRESS = :NEW.ADDRESS,
             DWT.SALARY = :NEW.SALARY;
    END IF;
    MERGE INTO CUSTOMERS_D D
    USING DUAL
    ON (D.ID = :NEW.ID)
    WHEN MATCHED THEN
      UPDATE SET D.NAME = :NEW.NAME,
             D.AGE = :NEW.AGE,
             D.ADDRESS = :NEW.ADDRESS,
             D.SALARY = :NEW.SALARY
    WHEN NOT MATCHED THEN
      INSERT
        (D.ID, D.NAME, D.AGE, D.ADDRESS, D.SALARY) VALUES
        (:NEW.ID, :NEW.NAME, :NEW.AGE, :NEW.ADDRESS, :NEW.SALARY);
  END IF;

end test;

【问题讨论】:

  • 嗯,每个人第一次学习语言时都是新的。想出一个代码,总有一些例子远离单一的谷歌搜索。仅当您在任何地方都找不到解决方案时才提出问题。给我一个代码问题在 SO 中并不总是受欢迎的
  • 当然考希克。谢谢。我正在通过添加我尝试过的代码来编辑上面的帖子
  • 好吧,我在您的触发代码中看不到一点。如果最终您要做的是使用cutomerscutomers_d 上发送Merge,则它们都将包含相同的数据,但已删除的数据除外。因此,您基本上会浪费资源,因为您拥有 2 个具有几乎相同数据的表。
  • 这意味着当cutomers 发生变化(即更新或插入)时,您只需要insert into CUSTOMERS_D,如果我错了,请告诉我?
  • 好的。我的实际计划是,每当源数据发生变化时,触发器必须通知并将这些更改的记录插入到 1 个表中。然后这个数据集需要转换为 JSON 文件,我将使用 PubSub 作为 Google Cloud 事件发布.然后将此数据加载到Bigquery。这是我的整体流程。可能是我上面的解释不恰当。作为测试目的的一部分,我将 CUST 作为源,将 CUST_D 作为需要转换为 JSON 文件的表。请指教

标签: oracle plsql database-trigger


【解决方案1】:

你现在的触发器有太多不必要的结构,你应该去掉。每当从customers 表中添加或插入记录时,您所需要的(正如您在 cmets 中所确认的那样)是一条插入到customers_d 中的语句。
我建议您添加另一列指示交易时间 -MODIFIED_TIME

CREATE OR REPLACE TRIGGER CUST_TRIG 
  AFTER INSERT OR UPDATE ON CUSTOMERS 
FOR EACH ROW 
begin
   INSERT INTO CUSTOMERS_D
     (ID, NAME, AGE, ADDRESS, SALARY,modified_time ) 
       values (:new.ID,
       :new.NAME, 
       :new.AGE, 
       :new.ADDRESS, 
       :new.SALARY,
       systimestamp);
end ;
/

DEMO

【讨论】:

    【解决方案2】:

    乍一看,当插入新记录时,我可以看到此触发器中的一个问题,OLD.ID 将为 NULL,因此 WHEN ((OLD.ID &lt;&gt; NEW.ID) 将是 FALSE,并且触发器不会在 INSERT 时调用到 CUST_TRIG。只需添加以下条件:

    FOR EACH ROW  WHEN ((OLD.ID <> NEW.ID) OR (OLD.ID IS NULL))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-23
      • 1970-01-01
      • 1970-01-01
      • 2021-10-15
      相关资源
      最近更新 更多