Oracle 触发器迁移至KingbaseES常见的问题

oracle数据库的触发器迁移到KingbaseES的时候经常会出现一下两类错误:
1.SQL 错误 [42809]: 错误: "xxxxxxxx" 是一个视图。Detail: 视图上的触发器不能有转换表。
2.SQL 错误 [0A000]: 错误: 不能为具有多个事件的触发器指定转换表
这两类问题都可以通过使用触发器函数来进行改写。

下面来看下具体的例子:
示例1

oracle触发器内容:
CREATE TRIGGER TRG_FIN_IPR_INMAININFO INSTEAD OF
UPDATE ON VIEW_FIN_IPR_INMAININFOMONTHER REFERENCING NEW AS N FOR EACH ROW DECLARE -- LOCAL VARIABLES HERE
  BEGIN IF :N.IN_STATE <> 'O'
  AND (:OLD.BED_NO <> :N.BED_NO OR :OLD.IN_STATE <> :N.IN_STATE ) THEN
UPDATE FIN_IPR_INMAININFO
SET IN_STATE = :N.IN_STATE,BED_NO = :N.BED_NO
WHERE INPATIENT_NO IN (SELECT BABY_INPATIENT_NO FROM FIN_IPR_BABYINFO
    WHERE INPATIENT_NO = :N.INPATIENT_NO) AND BABY_FLAG = '0';
END IF;
END TRG_FIN_IPR_INMAININFO;

迁移时报错:SQL 错误 [42809]: 错误: "VIEW_FIN_IPR_INMAININFOMONTHER" 是一个视图。Detail: 视图上的触发器不能有转换表.

使用触发器函数改写: 
创建触发器函数
CREATE OR REPLACE FUNCTION TRG_FIN_IPR_INMAININFO_FUN()
RETURNS TRIGGER AS $$
BEGIN 
  IF NEW.IN_STATE <> 'O' AND (OLD.BED_NO <> NEW.BED_NO OR OLD.IN_STATE <> NEW.IN_STATE ) THEN 
    UPDATE FIN_IPR_INMAININFO SET IN_STATE = NEW.IN_STATE,BED_NO = NEW.BED_NO
    WHERE INPATIENT_NO IN (SELECT BABY_INPATIENT_NO FROM FIN_IPR_BABYINFO
    WHERE INPATIENT_NO = NEW.INPATIENT_NO) AND BABY_FLAG = '0';
    RETURN NEW;
  END IF;
END;
$$LANGUAGE PLPGSQL;

使用触发器函数创建触发器
CREATE TRIGGER TRG_FIN_IPR_INMAININFO INSTEAD OF UPDATE ON VIEW_FIN_IPR_INMAININFOMONTHER
    FOR EACH ROW EXECUTE FUNCTION TRG_FIN_IPR_INMAININFO_FUN();

示例2

oracle触发器内容:
CREATE TRIGGER "TRG_ESB_ORDER_DETAIL" AFTER
INSERT OR UPDATE OF VALID_FLAG, VALID_DATE,VALID_USERCD OR DELETE 
ON MET_IPM_EXECDRUG REFERENCING NEW AS MYNEW OLD AS MYOLD FOR EACH ROW DECLARE V_ERROCODE NUMBER;
V_ERROTEXT VARCHAR2(200);
BEGIN 
  IF INSERTING THEN
    INSERT INTO ESB_ORDER_DETAIL_EVENTS(EVENT_ID,OBJECT_KEY,OBJECT_NAME,OBJECT_VERB,EVENT_PRIORITY,EVENT_TIME,EVENT_STAUS,EVENT_COMMENT)
    VALUES(ESB_EVENT_SEQ.NEXTVAL,:MYNEW.EXEC_SQN,'MET_IPM_EXECDRUG','INSERT',3,SYSDATE,0,'IPMOMDEX INSERT');
    ELSIF UPDATING THEN
    INSERT INTO ESB_ORDER_DETAIL_EVENTS(EVENT_ID,OBJECT_KEY,OBJECT_NAME,OBJECT_VERB,EVENT_PRIORITY,EVENT_TIME,EVENT_STAUS,EVENT_COMMENT)
    VALUES(ESB_EVENT_SEQ.NEXTVAL,:MYNEW.EXEC_SQN,'IPMOMDEX','UPDATE',3,SYSDATE,0,'IPMOMDEX UPDATE');
    ELSIF DELETING THEN
    INSERT INTO ESB_ORDER_DETAIL_EVENTS(EVENT_ID,OBJECT_KEY,OBJECT_NAME,OBJECT_VERB,EVENT_PRIORITY,EVENT_TIME,EVENT_STAUS,EVENT_COMMENT)
    VALUES(ESB_EVENT_SEQ.NEXTVAL,OLD.EXEC_SQN,'IPMOMDEX','DELETE',3,SYSDATE,0,'IPMOMDEX  DELETE');
  END IF;
EXCEPTION
    WHEN OTHERS THEN V_ERROCODE: = SQLCODE;
    V_ERROTEXT: = SUBSTR(SQLERRM, 1, 200);
    INSERT INTO ESB_ERRO_LOG(ERRO_CODE, ERRO_INFO, ERRO_TIME)
    VALUES(V_ERROCODE, V_ERROTEXT, SYSDATE);
END;

迁移时报错:SQL 错误 [0A000]: 错误: 不能为具有多个事件的触发器指定转换表

使用触发器函数改写:
CREATE OR REPLACE FUNCTION TRG_ESB_ORDER_DETAIL_FUN() RETURNS TRIGGER AS $$
DECLARE
V_ERROCODE NUMBER;
V_ERROTEXT VARCHAR2(200);
BEGIN
  IF (TG_OP = 'INSERT') THEN 
    INSERT INTO ESB_ORDER_DETAIL_EVENTS(EVENT_ID,OBJECT_KEY,OBJECT_NAME,OBJECT_VERB,EVENT_PRIORITY,EVENT_TIME,EVENT_STAUS,EVENT_COMMENT)
    VALUES(ESB_EVENT_SEQ.NEXTVAL,NEW.EXEC_SQN,'MET_IPM_EXECDRUG','INSERT',3,SYSDATE,0,'IPMOMDEX INSERT');
  ELSIF (TG_OP = 'UPDATE') THEN
    INSERT INTO ESB_ORDER_DETAIL_EVENTS(EVENT_ID,OBJECT_KEY,OBJECT_NAME,OBJECT_VERB,EVENT_PRIORITY,EVENT_TIME,EVENT_STAUS,EVENT_COMMENT)
    VALUES(ESB_EVENT_SEQ.NEXTVAL,NEW.EXEC_SQN,'IPMOMDEX','UPDATE',3,SYSDATE,0,'IPMOMDEX UPDATE');
  ELSIF (TG_OP = 'DELETE') THEN
    INSERT INTO ESB_ORDER_DETAIL_EVENTS(EVENT_ID,OBJECT_KEY,OBJECT_NAME,OBJECT_VERB,EVENT_PRIORITY,EVENT_TIME,EVENT_STAUS,EVENT_COMMENT)
    VALUES(ESB_EVENT_SEQ.NEXTVAL,OLD.EXEC_SQN,'IPMOMDEX','DELETE',3,SYSDATE,0,'IPMOMDEX  DELETE');
  END IF;
  RETURN NEW;
EXCEPTION
    WHEN OTHERS THEN 
    V_ERROCODE := SQLCODE;
    V_ERROTEXT := SUBSTR(SQLERRM, 1, 200);
    INSERT INTO ESB_ERRO_LOG(ERRO_CODE, ERRO_INFO, ERRO_TIME)
    VALUES(V_ERROCODE, V_ERROTEXT, SYSDATE);
END;
$$LANGUAGE PLPGSQL;


CREATE TRIGGER "TRG_ESB_ORDER_DETAIL" AFTER
INSERT OR UPDATE OF VALID_FLAG, VALID_DATE,VALID_USERCD OR DELETE 
ON MET_IPM_EXECDRUG FOR EACH ROW EXECUTE FUNCTION TRG_ESB_ORDER_DETAIL_FUN();

在本文中,我们探讨了在将Oracle数据库的触发器迁移到KingbaseES过程中遇到的两个常见错误。
示例1和示例2提供了具体的改写方法,帮助我们理解如何在KingbaseES中重新实现这些触发器的功能。这种方法不仅解决了特定的错误,还提供了一种在迁移过程中保持数据完整性和业务逻辑连续性的策略。

posted @ 2024-03-28 15:32  KINGBASE研究院  阅读(101)  评论(0编辑  收藏  举报