删除USER(具有权限)如果在Postgres中存在

时间:2016-11-29 09:24:28

标签: postgresql automated-tests

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

我的数据库是Postgres v9.6

背景:

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

  • 创建用户(如果尚不存在)
  • 使用某些表(如果尚不存在)创建模式

和拆解将:

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

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

根据Postgres的文件:

  

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

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

但是因为DROP OWNED BY或REVOKE似乎没有任何条件条款,我不知道如何做到这一点?

2 个答案:

答案 0 :(得分:3)

也许我错过了一些更简单的解决方案,但是问题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;

答案 1 :(得分: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$$;