将触发器从Oracle 11g迁移到Postgresql 8.4

时间:2014-08-27 20:21:43

标签: oracle postgresql oracle11g postgresql-8.4 triggers

我在Oracle中的触发器看起来像这样......

CREATE OR REPLACE TRIGGER example$example
    BEFORE UPDATE OR DELETE ON example
    FOR EACH ROW
    BEGIN
        INSERT INTO
            example$
        VALUES
            (
            :old.key,
            :old.name,
            :old.describe
            seq.nextVal
            );
    END;

我以为我可以用这个简单地翻译成Postgresql ......

CREATE OR REPLACE TRIGGER example$example
    BEFORE UPDATE OR DELETE ON example
    FOR EACH ROW
    BEGIN
        INSERT INTO
            example$
        VALUES
            (
            OLD.key,
            OLD.name,
            OLD.describe,
            NEXTVAL('seq')
            );
    END;

我在INSERT语句结束时收到错误。 Postgresql中没有匿名块吗?我必须把它放在一个功能中吗?如果是这样,函数的返回值是多少? NULL?

修改

所以我现在正在尝试这个......

CREATE OR REPLACE FUNCTION example$trigger()
    RETURNS TRIGGER AS
    $func$
    BEGIN
        INSERT INTO
            example$
            (
            key,
            name,
            describe,
            seq
            )
        VALUES
            (
            OLD.key,
            OLD.name,
            OLD.describe,
            NEXTVAL('seq')
            );
    END
    $func$ LANGUAGE plpgsql 


CREATE OR REPLACE TRIGGER example$trigger
    AFTER UPDATE OR DELETE ON example
    FOR EACH ROW
    EXECUTE PROCEDURE example$trigger;

该功能通过触发报告编译而没有错误......

ERROR:  syntax error at or near "TRIGGER"
LINE 1: CREATE OR REPLACE TRIGGER example$trigger
                          ^

********** Error **********

ERROR: syntax error at or near "TRIGGER"
SQL state: 42601
Character: 19

1 个答案:

答案 0 :(得分:5)

Postgres中的触发器不能直接提供触发器代码,而是调用触发器函数,可以从任意数量的触发器调用,但通常它们是针对一个特定事件自定义的特别的表。

触发功能:

CREATE OR REPLACE FUNCTION trg_some_tbl_foo()
  RETURNS trigger AS
$func$
BEGIN

INSERT INTO some_tbl(key, name, describe)   -- or some_other_tbl?
VALUES (OLD.key, OLD.name, OLD.describe);

RETURN OLD;

END
$func$ LANGUAGE plpgsql 

Trigger:

CREATE TRIGGER foo         -- not:  "CREATE OR REPLACE" !
AFTER UPDATE OR DELETE ON some_tbl
FOR EACH ROW EXECUTE PROCEDURE trg_some_tbl_foo()
  • 使其成为AFTER触发器以简化。 BEFORE触发器必须RETURN NEW才能使更新生效,但在NEW触发器中看不到DELETE。所以你需要IF TG_OP = ...等。

  • 始终为持久性INSERT语句提供目标列表。这在Oracle触发器中同样糟糕。

  • 您可能有一个包含serial列的表格。只是不在插入中提及它,序列中的下一个ID会自动插入。

这里有很多代码示例。