迁移 Oracle 到 PostgreSQL: compound trigger

五月 17, 2023

摘要:在本教程中,您将学习如何将 Oracle 的复合触发器 compound trigger 迁移到 PostgreSQL。

假设我们已经创建了一个表,并为该表创建了四个触发器。我们创建了 before statement 触发器、before each row 触发器、after each row 触发器和 after statement 触发器。oracle 可以将所有这些单独的触发器组合到一个触发器中,这样的触发器叫做复合触发器。我们可以将所有这 4 个触发器组合成一个触发器。我们将为每个触发器提供相关行为的定义。

复合触发器

表上的单个触发器,允许您为以下四个时间点指定要触发的操作:

  • 在触发语句之前
  • 在触发语句影响的每一行之前
  • 在触发语句影响的每一行之后
  • 在触发语句之后

Oracle 从 版本 11g 开始支持复合触发器。让我们继续查看使用复合触发器的示例,并了解有关它的更多信息。

准备工作

为了测试复合触发器,让我们通过执行下面的 CREATE TABLE 语句创建一个表 emp_test。

CREATE TABLE emp_test (
  emp_id number,
  first_name varchar2(100)
);

Oracle 示例

正如我们所讨论的,复合触发器由四个触发器组成。我们将在复合触发器中包含所有这些触发器。下面是复合触发器的语法。

CREATE OR REPLACE TRIGGER comp_test
FOR INSERT OR UPDATE OR DELETE
ON emp_test
COMPOUND TRIGGER
-- we can define any variables here..
  BEFORE STATEMENT IS
  BEGIN
    DBMS_OUTPUT.PUT_LINE('1');
  END BEFORE STATEMENT;

  BEFORE EACH ROW IS
  BEGIN
    DBMS_OUTPUT.PUT_LINE('2');
  END BEFORE EACH ROW;
  
  AFTER EACH ROW IS
  BEGIN
    DBMS_OUTPUT.PUT_LINE('3');
  END AFTER EACH ROW;
  
  AFTER STATEMENT IS
  BEGIN
    DBMS_OUTPUT.PUT_LINE('4');
  END AFTER STATEMENT;
END;

代码非常简单。我们已经创建了名为 comp_test 的复合触发器,用于在表 emp_test 上的插入或更新或删除事件。

因此,我们有四个触发代码。如果执行 before statement 触发器,则 DBMS 输出将显示 “1”。如果执行 before each row 触发器,DBMS 输出将显示 “2”。如果执行 after each row 触发器,则 DBMS 输出将显示 “3”。同样,after statement 触发器会将 DBMS 输出显示为 “4”。

PostgreSQL 示例

PostgreSQL 不支持复合触发器,你可以将它转换为普通的触发器。在创建触发器前,我们需要执行 CREATE FUNCTION 语句创建触发器函数。

CREATE FUNCTION comp_test_func() RETURNS trigger AS $$
    BEGIN
        IF (TG_WHEN = 'BEFORE' AND TG_LEVEL = 'STATEMENT') THEN
            RAISE NOTICE '1';
        ELSIF (TG_WHEN = 'BEFORE' AND TG_LEVEL = 'ROW') THEN
            RAISE NOTICE '2';
        ELSIF (TG_WHEN = 'AFTER' AND TG_LEVEL = 'ROW') THEN
            RAISE NOTICE '3';
        ELSIF (TG_WHEN = 'AFTER' AND TG_LEVEL = 'STATEMENT') THEN
            RAISE NOTICE '4';
        END IF;
        RETURN NEW;
    END;
$$ LANGUAGE plpgsql;

并针对每个事件,执行 CREATE TRIGGER 语句创建对应的触发器。

CREATE TRIGGER trig_test_before_stmt
    BEFORE INSERT OR UPDATE OR DELETE ON emp_test
    FOR EACH STATEMENT
    EXECUTE FUNCTION comp_test_func();

CREATE TRIGGER trig_test_before_row
    BEFORE INSERT OR UPDATE OR DELETE ON emp_test
    FOR EACH ROW
    EXECUTE FUNCTION comp_test_func();

CREATE TRIGGER trig_test_after_row
    AFTER INSERT OR UPDATE OR DELETE ON emp_test
    FOR EACH ROW
    EXECUTE FUNCTION comp_test_func();

CREATE TRIGGER trig_test_after_stmt
    AFTER INSERT OR UPDATE OR DELETE ON emp_test
    FOR EACH STATEMENT
    EXECUTE FUNCTION comp_test_func();