阻止除触发器之外的列更新

bsa*_*bsa 2 postgresql permissions triggers

是否可以配置Postgres数据库,使得特定的列只能由触发器更新,而仍然允许触发器本身响应角色的更新而执行,而无权更新该列?如果是这样,怎么办?

例如,给定的表和这样的触发器:

CREATE TABLE a(
  id serial PRIMARY KEY,
  flag boolean NOT NULL DEFAULT TRUE,
  data text NOT NULL
);

CREATE TABLE b(
  id serial PRIMARY KEY,
  updated_on DATE NOT NULL DEFAULT CURRENT_DATE,
  a_id INTEGER NOT NULL,
  FOREIGN KEY (a_id) references a(id)
);

CREATE FUNCTION update_aflag() RETURNS trigger AS $update_aflag$
  BEGIN
    UPDATE a
    SET flag = FALSE
    WHERE id = NEW.a_id;
    RETURN NEW;
  END;
$update_aflag$ LANGUAGE plpgsql;

CREATE TRIGGER update_aflag_trigger
  AFTER INSERT ON b
  FOR EACH ROW
  EXECUTE PROCEDURE update_aflag()
;
Run Code Online (Sandbox Code Playgroud)

我想定义一个角色,该角色无权a.flag使用UPDATE语句直接更新,但可以flag通过触发器间接更新。

Cra*_*ger 5

是的,这可以通过SECURITY DEFINER触发功能实现。触发功能以有权修改flag列的角色运行,但GRANT普通用户则无此权限。您应该将触发函数创建为将授予其所需权限的角色。

这要求应用程序不能以拥有表的用户身份运行,当然也不能以超级用户身份运行。

您可以GRANT为用户向其他列提供列更新权限,而只需忽略该flag列。需要注意的是GRANT荷兰国际集团UPDATE所有列,然后REVOKE荷兰国际集团它flag就会工作,这是不一样的东西。