如何创建 Postgres 触发器以确保字段不可更新

use*_*092 8 postgresql trigger

我正在尝试创建一个 Postgres 触发器,以确保在设置列的值后,它无法更新(基本上使其成为只读)。到目前为止,我已经提出了以下草案触发器。

1) 首先,我在正确的轨道上吗?
2) 有回报价值NEW吗?
3) 我必须original_idNEW.?

CREATE FUNCTION check_id_change() RETURNS TRIGGER AS $$
    BEGIN
        IF OLD.original_id <> NEW.original_id THEN
            RAISE EXCEPTION 'cannot change original_id'; 
        END IF;
        RETURN NEW;
    END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER client_update_trigger AFTER UPDATE ON client FOR EACH ROW
      EXECUTE PROCEDURE check_id_change();
Run Code Online (Sandbox Code Playgroud)

mah*_*nah 13

BEFORE UPDATE在您的特定列上创建一个original_id
注意因为使用 DB 的应用程序应该知道它的约束,因此最好在列更新时引发异常,以便通知应用程序层失败,而不是仅仅忽略更新。

CREATE OR REPLACE FUNCTION check_id_change()
  RETURNS TRIGGER AS
$BODY$
BEGIN
  IF NEW."original_id" IS DISTINCT FROM OLD."original_id"
  THEN
    RAISE EXCEPTION '"original_id" column cannot get updated';
  END IF;

  RETURN NEW;
END;
$BODY$ LANGUAGE PLPGSQL;

CREATE TRIGGER client_update_trigger
BEFORE UPDATE OF "original_id"
  ON "client"
FOR EACH ROW
EXECUTE PROCEDURE check_id_change();
Run Code Online (Sandbox Code Playgroud)

或使用WHEN条件

CREATE OR REPLACE FUNCTION check_id_change()
  RETURNS TRIGGER AS
$BODY$
BEGIN
  RAISE EXCEPTION '"original_id" column cannot get updated';
END;
$BODY$ LANGUAGE PLPGSQL;

CREATE TRIGGER client_update_trigger
BEFORE UPDATE OF "original_id"
  ON "client"
FOR EACH ROW
WHEN (NEW."original_id" IS DISTINCT FROM OLD."original_id")
EXECUTE PROCEDURE check_id_change();
Run Code Online (Sandbox Code Playgroud)

注意使用IS DISTINCT FROM比较而不是<>!=除非该列具有NOT NULL或您确定它的值永远不会是NULL.


Nei*_*gan 6

使用before update触发器。

您是要引发异常还是只是让它默默地不更改值?

是的,你应该返回NEW

是的,您应该在列名前加上NEWOLD

如果您不想引发异常,可以使用它:

create function check_id_change() returns trigger language plpgsql as $$
begin

  new.original_id = old.original_id;

  return new;

end $$;
Run Code Online (Sandbox Code Playgroud)