只有特定用户才能修改 A 列
...
如果...为NULL,其他用户应该能够更新该列。
从public 和其他不应该拥有特权的所有人撤消UPDATE(和DELETE ?!?)。
REVOKE UPDATE ON TABLE tbl FROM public;
REVOKE UPDATE ON TABLE tbl FROM ...
创建一个(组)角色some_users,允许更新col_a(仅此而已):
CREATE ROLE some_users;
GRANT SELECT, UPDATE (col_a) ON TABLE tbl TO some_users;
为什么是SELECT? The manual on GRANT:
实际上,任何重要的UPDATE 命令都需要SELECT
特权也是如此,因为它必须引用表列来确定
要更新哪些行,和/或计算列的新值。
这样,您就有了一个单点,您可以在其中分配列的权限。
创建另一个(组)角色certain_users 可以做所有some_users 可以(加上更多):
CREATE ROLE certain_users;
GRANT some_users TO certain_users;
根据需要将这些角色的成员资格授予用户角色:
GRANT some_users TO lowly_user;
GRANT certain_users TO chief_user;
创建一个条件触发器,类似于 @Daniel provided,但使用 pg_has_role() 的另一个条件:
CREATE TRIGGER tbl_value_trigger
BEFORE UPDATE ON tbl
FOR EACH ROW
WHEN (OLD.col_a IS NOT NULL AND NOT pg_has_role('some_users', 'member'))
EXECUTE PROCEDURE always_fail();
使用触发功能:
CREATE FUNCTION always_fail()
RETURNS trigger
LANGUAGE plpgsql AS
$func$
BEGIN
-- To fail with exception, rolling back the whole transaction
-- use this instead:
-- RAISE EXCEPTION 'value is not null';
-- Do nothing instead, letting the rest of the transaction commit.
-- Requires BEFORE trigger.
RAISE WARNING 'col_a IS NOT NULL. User % is too ambitious!', current_user;
RETURN NULL; -- effectively aborts UPDATE
END
$func$;
现在:
- 限制公众完全更新表格。
-
允许
some_users 和certain_users 更新列col_a(仅此而已),
- 仅来自
certain_users 的更改通过一次col_a is NOT NULL。
注意超级用户自动成为任何组的成员。因此,NOT pg_has_role(...) 表单 启用 超级用户,而逆向逻辑可能会禁止超级用户更新列。