我需要放弃这个角色。
在同一集群的每个数据库中运行此命令,其中角色可能拥有任何东西或具有任何授予的权限:
REASSIGN OWNED BY some_role_name TO postgres;
DROP OWNED BY some_role_name;
postgres 是默认超级用户,您可以选择任何其他用户。它将拥有旧角色当前拥有的对象。在REASSIGN OWNED 之后,没有任何对象会被同一用户拥有。运行DROP OWNED 可能看起来不直观。该命令的措辞具有误导性,因为它也撤销了同一数据库中角色的所有权限和默认权限。 The manual:
DROP OWNED 删除当前数据库中由指定角色之一拥有的所有对象。 在当前数据库中的对象和共享对象(数据库、表空间)上授予给定角色的任何权限也将被撤销。
我的大胆强调。
您仍然必须在每个数据库中执行它,其中角色拥有任何东西或具有任何授予的权限。手册:
因为REASSIGN OWNED 不会影响其他数据库中的对象,所以通常需要在每个包含要删除的角色拥有的对象的数据库中执行此命令。
最后,运行(一次):
DROP role some_role_name;
角色存储在集群范围的系统目录中,而对象的所有权和权限存储在数据库本地系统目录中。
此相关答案中的详细说明:
有一个相关的page in the manual with instructions。
全自动化
没有一个命令可以做到这一切。但是你可以让 Postgres 为你生成一个完整的 psql 脚本。
角色的依赖关系存储在系统目录pg_shdepend中:
此信息允许 PostgreSQL 在尝试删除这些对象之前确保它们未被引用。
由于我们(可能)需要连接到不同的数据库,我们需要 psql 元命令 (\c my_database) 和 SQL DDL 命令的组合,如上所示。在您的数据库集群中的某处创建此函数一次:
CREATE OR REPLACE FUNCTION f_generate_ddl_to_remove_role(dead_role_walking regrole)
RETURNS text
LANGUAGE sql AS
$func$
SELECT concat_ws(
E'\n'
,(SELECT string_agg(format(E'\\c %I\nREASSIGN OWNED BY %2$s TO postgres; DROP OWNED BY %2$s;'
, d.datname, dead_role_walking)
, E'\n')
FROM (
SELECT DISTINCT dbid
FROM pg_shdepend
WHERE refobjid = dead_role_walking
) s
JOIN pg_database d ON d.oid = s.dbid)
, format(E'DROP role %s;\n', dead_role_walking)
)
$func$;
呼叫:
SELECT f_generate_ddl_to_remove_role('some_role_name');
产生如下字符串:
\c my_db1
REASSIGN OWNED BY some_role_name TO postgres; DROP OWNED BY some_role_name;
\c my_db2
REASSIGN OWNED BY some_role_name TO postgres; DROP OWNED BY some_role_name;
DROP role some_role_name;
或者,如果角色不拥有任何东西并且没有特权,那么:
DROP role some_role_name;
如果您提供不存在的角色名称,则会收到错误消息。
将字符串(不包含单引号)复制到以超级用户(如postgres)打开的 psql 会话中。或者将 bash 脚本与它连接起来。全部完成。
有几个相关的答案,对动态SQL有更多解释: