是否可以同时设置PostgreSQL数据库中所有对象的所有者?


Answers:


22

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

杰里米(Jeremy)的答案虽然基本上可以解决问题,但不建议一般大众使用。它无条件地更改架构中的所有功能。您确定不影响系统功能或附加模块未安装功能吗?
更改已经属于指定所有者的功能的所有者也是毫无意义的。

首先,检查是否REASSIGN OWNED可以为您工作:

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

您必须列出所有要明确放弃的角色。但是它也重新分配了功能

要将给定架构中的所有功能(没有其他对象)分配给新所有者(可选,与先前所有者无关):

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_%'

这将生成规范的SQL命令ALTER FUNCTION ...以更改所有功能(在指定架构中)。您可以在执行命令之前先检查命令-一次或一次检查所有命令:

ALTER FUNCTION public.bar(text, text) OWNER TO foo;
ALTER FUNCTION public.foo(x integer) OWNER TO foo;
...

我包括了一些注释的WHERE子句,您可能希望使用它们来过滤结果。

强制转换为regprocedure会产生带有参数的有效函数名称,必要时将其双引号,并在必要时对current进行模式限定search_path

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

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

在Postgres 9.5或更高版本中,您可以使用新的对象标识符类型regnamespaceregrole简化查询:

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_%'

1

我使用此函数来更改表,函数,类型等的所有者。您可以更改游标的查询以使其适应您的需求。

CREATE OR REPLACE FUNCTION fn_setowner(varchar(50), boolean) RETURNS void AS
$BODY$
DECLARE
p_owner ALIAS FOR $1;
p_debug ALIAS FOR $2;
v_i integer := 0;
v_sql text;

--  CURSORS
-- SCHEMA
pesquemas CURSOR FOR
    SELECT quote_ident(schema_name) as nombre_esquema from information_schema.schemata WHERE schema_name NOT LIKE 'pg_%'
    and schema_name NOT IN ('information_schema') ORDER BY 1 ASC;

-- TABLE
ptablas CURSOR FOR
    SELECT quote_ident(table_schema) || '.' || quote_ident(table_name) as nombre_tabla, * FROM information_schema.tables
    WHERE table_schema NOT IN ('pg_catalog', 'information_schema')
    AND table_type <> 'FOREIGN TABLE' ORDER BY 1 ASC;

-- FUNCTION
pfunciones CURSOR FOR
    SELECT quote_ident(b.nspname) || '.' || quote_ident(a.proname) || '(' || pg_catalog.oidvectortypes(a.proargtypes) || ')' as nombre_function 
    FROM pg_proc a  INNER JOIN pg_namespace b on a.pronamespace = b.oid 
    WHERE b.nspname NOT IN ('pg_catalog', 'information_schema') AND proisagg = 'f'
    AND a.proname not like 'fsym_%' AND a.proname not like 'dblink%' ORDER BY 1 ASC;

-- SEQUENCE
psecuencias CURSOR FOR
    SELECT quote_ident(sequence_schema) || '.' || quote_ident(sequence_name) as nombre_secuencia FROM information_schema.sequences
    WHERE sequence_schema NOT IN ('pg_catalog', 'information_schema') ORDER BY 1 ASC;

-- TYPE
ptipos CURSOR FOR
    SELECT quote_ident(n.nspname) || '.' || quote_ident(t.typname) as nombre_tipo
    FROM pg_type t
    LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace 
    WHERE (t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) 
    AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)
    AND n.nspname NOT IN ('pg_catalog', 'information_schema') ORDER BY 1 ASC;


BEGIN
--  CHECK LOGIN
    IF NOT EXISTS (SELECT 1 FROM pg_user WHERE usename = p_owner) THEN                     
        RAISE EXCEPTION 'Login role not exists --> %', p_owner
            USING HINT = 'Please specify correct login and try again.';
    END IF;

    v_i = 0;
    if (p_debug) THEN
    RAISE NOTICE '--########## CHANGE SCHEMA OWNER ##########--';
    END IF;
    FOR resquema IN pesquemas LOOP
        v_sql = 'ALTER SCHEMA ' || resquema.nombre_esquema || ' OWNER TO ' || quote_ident(p_owner) || ';';
        if (p_debug) THEN RAISE NOTICE '%', v_sql; END IF;
        EXECUTE v_sql;
        v_i = v_i + 1;
    END LOOP;
    if (p_debug) THEN
    RAISE NOTICE '--@@@@@@ SCHEMAS WITH OWNER % TOTAL = % @@@@@@--', p_owner, CAST(v_i AS VARCHAR);
    END IF;

    v_i = 0;
    if (p_debug) THEN
    RAISE NOTICE '--########## CHANGE TABLE OWNER ##########--';
    END IF;
    FOR rtables IN  ptablas LOOP
        v_sql = 'ALTER TABLE ' || rtables.nombre_tabla || ' OWNER TO ' || quote_ident(p_owner) || ';';
        if (p_debug) THEN RAISE NOTICE '%', v_sql; END IF;
        EXECUTE v_sql;
        v_i = v_i + 1;
    END LOOP;
    if (p_debug) THEN
    RAISE NOTICE '--@@@@@@ TABLES WITH OWNER % TOTAL = % @@@@@@--', p_owner, CAST(v_i AS VARCHAR);
    END IF;

    v_i = 0;
    if (p_debug) THEN
    RAISE NOTICE '--########## CHANGE FUNCTION OWNER ##########--';
    END IF;
    FOR rfunction IN  pfunciones LOOP
        v_sql = 'ALTER FUNCTION ' || rfunction.nombre_function || ' OWNER TO ' || quote_ident(p_owner) || ';';
        if (p_debug) THEN RAISE NOTICE '%', v_sql; END IF;
        EXECUTE v_sql;
        v_i = v_i + 1;
    END LOOP;
    if (p_debug) THEN
    RAISE NOTICE '--@@@@@@ FUNCTIONS WITH OWNER % TOTAL = % @@@@@@--', p_owner, CAST(v_i AS VARCHAR);
    END IF;

    v_i = 0;
    if (p_debug) THEN
    RAISE NOTICE '--########## CHANGE SEQUENCE OWNER ########## --';
    END IF;
    FOR rsecuencias IN  psecuencias LOOP
        v_sql = 'ALTER TABLE ' || rsecuencias.nombre_secuencia || ' OWNER TO ' || quote_ident(p_owner) || ';';             
        if (p_debug) THEN RAISE NOTICE '%', v_sql; END IF;
        EXECUTE v_sql;
        v_i = v_i + 1;
    END LOOP;
    if (p_debug) THEN
    RAISE NOTICE '--@@@@@@ SEQUENCES WITH OWNER % TOTAL = % @@@@@@--', p_owner, CAST(v_i AS VARCHAR);
    END IF;

    v_i = 0;
    if (p_debug) THEN
    RAISE NOTICE '--########## CHANGE TYPE OWNER ##########--';
    END IF;
    FOR rtipos IN  ptipos LOOP                
        v_sql = 'ALTER TYPE ' || rtipos.nombre_tipo || ' OWNER TO ' || quote_ident(p_owner) || ';';                
        if (p_debug) THEN RAISE NOTICE '%', v_sql; END IF;
        EXECUTE v_sql;
        v_i = v_i + 1;
    END LOOP;
    if (p_debug) THEN
    RAISE NOTICE '--@@@@@@  TYPES WITH OWNER % TOTAL = % @@@@@@--', p_owner, CAST(v_i AS VARCHAR);
    END IF;

END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE
  COST 100;

然后我执行(如果要调试输出,只需将第二个参数设置为true):

SELECT fn_setowner('demo', false);
DROP FUNCTION fn_setowner(varchar(30), boolean);

请注意,pg_proc.proisagg被替换皮克11 的发行说明说:替换系统表pg_procproisaggproiswindowprokind(彼得Eisentraut)`
欧文Brandstetter修改

0

这应该对以下功能起作用:

IFS=$'\n'
for fnc in `psql -qAt -c "SELECT  '\"' || p.proname||'\"' || '(' || pg_catalog.pg_get_function_identity_arguments(p.oid) || ')' FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_proc p ON p.pronamespace = n.oid WHERE n.nspname = 'public';" YOUR_DB`
do
  psql -c "alter function $fnc owner to NEW_OWNER" YOUR_DB
done

-1

您可以使用REASSIGN OWNED命令

只需以超级用户身份登录数据库并在下面执行

REASSIGN OWNED BY [old_user] TO [new_user];

这会将old_role拥有的所有对象(即表,序列,函数等)更改为新角色。您不必考虑用户拥有哪种对象,它们都将被更改。仅当您想更改该数据库本身的所有权时,才更改对象ALTER DATABASE name OWNER TO new_owner

这是最好的方法,因为将有n个表,顺序而不是循环和bash脚本


2
答案中提到了这是3年以来最多的投票。也有其局限性。
dezso

-7

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

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);

5
这是一个很好的问题(+1) - -1的回答虽然-我不希望任何人认为它是确定直接更新系统表像这样没有被十分肯定他们知道自己在做什么。
杰克说尝试topanswers.xyz 2011年

1
您正在要求证明它不会破坏某些内容,而我的反对意见是,如果您对某项内容不满意,则应说明其将破坏什么以及如何/为什么生成。如果您做不到,那么答案就不会是错误的,误导的,无用的或无助的,这是不赞成投票的标准。经过一些检查,在这种情况下,不难弄清楚元数据表中的关系,而且正如我所说,它工作得很顺利。举证责任应由低估者承担;我希望您将很难找到答案。
杰里米·霍洛瓦奇

1
我会随意引用@Erwin逐字记录:“如果您确切地知道自己在做什么,则应该只直接操纵系统目录。它可能会产生意想不到的副作用。或者您可能会破坏数据库(或整个数据库集群)无法修复”。Erwin知道他的东西(我也是)。在此处以及在postgres标签上检查我们的声誉和过去的答案。我的不赞成表示我的观点,我不提供任何证据,因为这些文档对我来说是足够的证据(其他人可以自己决定)。
杰克说尝试topanswers.xyz 2011年


6
使用Erwin方法有什么问题?您使用了(没有)明显问题的方法这一事实使我没有信心,也没有理由:有人可能会说我使用RAID0多年没有问题。
杰克说请尝试topanswers.xyz 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.