如果 Postgres 中存在,则删除 USER(具有特权)

Posted

技术标签:

【中文标题】如果 Postgres 中存在,则删除 USER(具有特权)【英文标题】:Drop USER (with privileges) IF EXIST in Postgres 【发布时间】:2016-11-29 09:24:28 【问题描述】:

我需要有条件地在 Postgres 中删除一个用户(如果它不存在)。 DROP USER IF EXIST 很好,但根据文档,我还需要先删除权限,但是 DROP OWNED 或 REVOKE 似乎有条件 IF EXIST 子句。如何有条件地删除我的用户的权限?

我的数据库是 Postgres v9.6

背景:

我正在尝试为 Postgres 创建一组设置/拆卸脚本,这些脚本将为一堆函数创建一个测试区域。安装脚本应该:

创建用户(如果尚不存在) 创建包含一些表的架构(如果尚不存在)

拆解将:

删除用户(如果存在) 删除架构(如果存在)

问题是测试套件可能会被中断并使数据库/测试区域处于损坏状态(例如,如果从未执行过拆卸),所以我必须在我的脚本中考虑这一点。

根据 Postgres 的文档:

如果角色仍然在集群的任何数据库中被引用,则无法删除该角色;如果是这样,将引发错误。在删除角色之前,您必须删除它拥有的所有对象(或重新分配其所有权)

我的用户有一个权限,即连接到我的测试架构所在的测试数据库。这是因为我打算使用测试用户登录并执行测试。

但是因为在 DROP OWNED BY 或 REVOKE 上似乎没有任何条件子句,我看不出如何做到这一点?

【问题讨论】:

【参考方案1】:

也许我缺少一些更简单的解决方案,但从问题Detect role in Postgresql dynamically 看来,一种解决方案是使用匿名代码块:

-- Only revoke if user 'my_user exists'
DO $$DECLARE count int;
BEGIN
SELECT count(*) INTO count FROM pg_roles WHERE rolname = 'my_user';
IF count > 0 THEN
    EXECUTE 'REVOKE CONNECT ON DATABASE "my-testdb" FROM my_user';
END IF;
END$$;

-- No privileges left, now it should be possible to drop
DROP USER IF EXISTS my_user;

【讨论】:

谢谢,这使我得到了此处描述的较短版本***.com/a/11299968/138256,它不需要“计数”变量【参考方案2】:

只是为了让其他人不必考虑如何使用@codebox评论中的链接来简化语句:

DO
$$BEGIN
IF EXISTS (SELECT FROM pg_roles WHERE rolname = 'my_user') THEN
    EXECUTE 'REVOKE CONNECT ON DATABASE "postgres" FROM my_user';
END IF;
END$$;

【讨论】:

以上是关于如果 Postgres 中存在,则删除 USER(具有特权)的主要内容,如果未能解决你的问题,请参考以下文章

Postgres:如果不存在则插入

Spring Data 错误:“HHH000389 不成功:如果存在则删除表”

如果键存在则删除字典项[重复]

Postgres 测试容器 - 如果存在级联,为啥要在删除表之前删除约束?

刷新或创建物化视图? Postgres

如何参数化 Postgres-custom-function 中的表和列,如果值存在则选择 PK,否则插入并返回 PK?