有没有办法同时设置 PostgreSQL 数据库中所有对象的所有者?

Jer*_*acs 14 postgresql metadata ddl functions owner

Stack Overflow Q & A Modify OWNER on all table 同时在 PostgreSQL 中描述了一些漂亮的方法来将表和其他对象更改为特定用户,并且它工作得很好,但是所有的建议似乎都忽略了我创建的函数。

是否有一种相当简单的方法来重置数据库中所有对象的所有者,包括函数?手工操作是非常不可取的。

Erw*_*ter 24

如果您确切地知道自己在做什么,您应该只直接操作系统目录。它可能会产生意想不到的副作用。或者,您可以损坏无法修复的数据库(或整个数据库集群)。

Jeremy 的回答,虽然基本上做到了这一点,对于普通大众来说是不可取的。它无条件地更改模式中的所有功能。您确定没有受到影响的系统功能或由附加模块安装的功能吗?
更改已经属于指定所有者的功能的所有者也是毫无意义的。

首先,检查是否REASSIGN OWNED适合您:

更改数据库角色拥有的数据库对象的所有权

您必须列出要明确否认的所有角色。但它也重新分配功能

要将给定模式中的所有功能(而不是其他对象)分配给新所有者(可以选择不考虑以前的所有者):

SELECT string_agg('ALTER FUNCTION '|| oid::regprocedure || ' OWNER TO foo;', E'\n') AS ddl
FROM   pg_catalog.pg_proc
WHERE  pronamespace = 'public'::regnamespace
-- AND relowner <> 'foo'::regrole
-- AND proname ~~ 'f_%'
Run Code Online (Sandbox Code Playgroud)

这会生成规范的 SQL 命令ALTER FUNCTION ...来更改所有函数(在指定的架构中)。执行前检查命令 - 一项一项或全部一次:

ALTER FUNCTION public.bar(text, text) OWNER TO foo;
ALTER FUNCTION public.foo(x integer) OWNER TO foo;
...
Run Code Online (Sandbox Code Playgroud)

转换 toregprocedure产生一个带参数的有效函数名,必要时用双引号括起来,必要时对当前search_path.

还使用对象标识符类型regnamespaceregrole为了简单起见。

我添加了一些WHERE您可能想用来过滤结果的注释子句。

可以将所有这些放入一个DO语句或一个函数中,如此相关答案中所示:

对于 Postgres 9.4 或更高版本

SELECT string_agg('ALTER FUNCTION ' || oid::regprocedure || ' OWNER TO foo;', E'\n') AS ddl
FROM   pg_catalog.pg_proc p
JOIN   pg_catalog.pg_namespace n ON n.oid = p.pronamespace
WHERE  n.nspname = 'public'
-- AND p.relowner <> (SELECT oid FROM pg_roles WHERE rolname = 'foo')
-- AND p.proname ~~ 'f_%'
Run Code Online (Sandbox Code Playgroud)

聚合函数string_agg()需要 PostgreSQL 9.0 或更高版本。在旧版本中用array_agg()和代替array_to_string()


Jer*_*acs -8

好吧,我没有找到一步式过程,但这可以处理我在数据库中可以看到的所有对象:

update pg_class 
SET relowner = (SELECT oid FROM pg_roles WHERE rolname = 'foo')
where relnamespace = (select oid 
                      from pg_namespace 
                      where nspname = 'public' 
                      limit 1);

update pg_proc 
set proowner = (select oid from pg_roles where rolname = 'foo')
where pronamespace = (select oid 
                      from pg_namespace 
                      where nspname = 'public' 
                      limit 1);
Run Code Online (Sandbox Code Playgroud)

  • 使用埃尔文的方法有什么问题吗?事实上,您使用该方法而没有出现(明显的)问题,这一事实让我没有信心,也不应该这样做:有人可能同样会说我已经使用 RAID0 多年,没有出现任何问题。 (6认同)
  • 这是一个很好的问题(+1)--1,但你的答案是-我不希望其他人认为可以直接更新这样的系统表,而不“非常”确定他们知道自己在做什么。 (5认同)