在PostgreSQL中同时修改所有表上的OWNER

时间:2009-08-28 16:32:26

标签: postgresql

如何修改PostgreSQL数据库中所有表的所有者?

我尝试了ALTER TABLE * OWNER TO new_owner,但它不支持星号语法。

24 个答案:

答案 0 :(得分:497)

您可以使用REASSIGN OWNED命令。

梗概:

REASSIGN OWNED BY old_role [, ...] TO new_role

这会将old_role拥有的所有对象更改为新角色。您不必考虑用户拥有的对象类型,它们都将被更改。请注意,它仅适用于单个数据库中的对象。它也不会改变数据库本身的所有者。

它可以回到至少8.2。他们的在线文档只能追溯到很久以前。

答案 1 :(得分:425)

参见REASSIGN OWNED命令

注意:作为@trygvis mentions in the answer belowREASSIGN OWNED命令至少从版本8.2开始可用,并且是一种更简单的方法。


由于您要更改所有表的所有权,因此您可能也需要视图和序列。这是我做的:

表:

for tbl in `psql -qAt -c "select tablename from pg_tables where schemaname = 'public';" YOUR_DB` ; do  psql -c "alter table \"$tbl\" owner to NEW_OWNER" YOUR_DB ; done

序列:

for tbl in `psql -qAt -c "select sequence_name from information_schema.sequences where sequence_schema = 'public';" YOUR_DB` ; do  psql -c "alter sequence \"$tbl\" owner to NEW_OWNER" YOUR_DB ; done

查看:

for tbl in `psql -qAt -c "select table_name from information_schema.views where table_schema = 'public';" YOUR_DB` ; do  psql -c "alter view \"$tbl\" owner to NEW_OWNER" YOUR_DB ; done

由于alter语句对于所有三个语句都是相同的,所以你可能会DRY稍微提高一点。


答案 2 :(得分:171)

这个:http://archives.postgresql.org/pgsql-bugs/2007-10/msg00234.php也是一个很好的快速解决方案,适用于一个数据库中的多个模式:

<强>表格

SELECT 'ALTER TABLE '|| schemaname || '.' || tablename ||' OWNER TO my_new_owner;'
FROM pg_tables WHERE NOT schemaname IN ('pg_catalog', 'information_schema')
ORDER BY schemaname, tablename;

<强>序列

SELECT 'ALTER SEQUENCE '|| sequence_schema || '.' || sequence_name ||' OWNER TO my_new_owner;'
FROM information_schema.sequences WHERE NOT sequence_schema IN ('pg_catalog', 'information_schema')
ORDER BY sequence_schema, sequence_name;

<强>视图

SELECT 'ALTER VIEW '|| table_schema || '.' || table_name ||' OWNER TO my_new_owner;'
FROM information_schema.views WHERE NOT table_schema IN ('pg_catalog', 'information_schema')
ORDER BY table_schema, table_name;

物化视图

基于this answer

SELECT 'ALTER TABLE '|| oid::regclass::text ||' OWNER TO my_new_owner;'
FROM pg_class WHERE relkind = 'm'
ORDER BY oid;

这将生成所有必需的ALTER TABLE / ALTER SEQUENCE / ALTER VIEW语句,复制这些语句并将其粘贴回plsql以运行它们。

通过执行以下操作检查psql中的工作:

\dt *.*
\ds *.*
\dv *.*

答案 3 :(得分:39)

如果要在一个sql语句中执行此操作,则需要定义http://wiki.postgresql.org/wiki/Dynamic_DDL中提到的exec()函数

CREATE FUNCTION exec(text) returns text language plpgsql volatile
  AS $f$
    BEGIN
      EXECUTE $1;
      RETURN $1;
    END;
$f$;

然后您可以执行此查询,它将更改表,序列和视图的所有者:

SELECT exec('ALTER TABLE ' || quote_ident(s.nspname) || '.' ||
            quote_ident(s.relname) || ' OWNER TO $NEWUSER')
  FROM (SELECT nspname, relname
          FROM pg_class c JOIN pg_namespace n ON (c.relnamespace = n.oid) 
         WHERE nspname NOT LIKE E'pg\\_%' AND 
               nspname <> 'information_schema' AND 
               relkind IN ('r','S','v') ORDER BY relkind = 'S') s;

$ NEWUSER是新所有者的postgresql新名称。

在大多数情况下,您需要成为超级用户才能执行此操作。您可以通过将所有者从您自己的用户更改为您所属的角色组来避免这种情况。

感谢RhodiumToad #postgresql帮助解决这个问题。

答案 4 :(得分:20)

我最近不得不更改数据库中所有对象的所有权。虽然表,视图,触发器和序列有些容易更改,但上述方法对于函数失败,因为签名是函数名称的一部分。当然,我有一个MySQL背景,并不熟悉Postgres。

但是, pg_dump 允许您只转储架构,这包含您需要的 ALTER xxx OWNER to yyy; 语句。这是关于主题的shell魔术

pg_dump -s YOUR_DB | grep -i 'owner to' | sed -e 's/OWNER TO .*;/OWNER TO NEW_OWNER;/i' | psqL YOUR_DB

答案 5 :(得分:16)

非常简单,试试吧......

 select 'ALTER TABLE ' || table_name || ' OWNER TO myuser;' from information_schema.tables where table_schema = 'public';

答案 6 :(得分:16)

我喜欢这个,因为它修改视图序列函数某个<的所有者一次性(在一个sql语句中)中的strong> schema ,无需创建函数,您可以直接在 PgAdmin III psql <中使用它/强>:

(在PostgreSql v9.2中测试)

DO $$DECLARE r record;
DECLARE
    v_schema varchar := 'public';
    v_new_owner varchar := '<NEW_OWNER>';
BEGIN
    FOR r IN 
        select 'ALTER TABLE "' || table_schema || '"."' || table_name || '" OWNER TO ' || v_new_owner || ';' as a from information_schema.tables where table_schema = v_schema
        union all
        select 'ALTER TABLE "' || sequence_schema || '"."' || sequence_name || '" OWNER TO ' || v_new_owner || ';' as a from information_schema.sequences where sequence_schema = v_schema
        union all
        select 'ALTER TABLE "' || table_schema || '"."' || table_name || '" OWNER TO ' || v_new_owner || ';' as a from information_schema.views where table_schema = v_schema
        union all
        select 'ALTER FUNCTION "'||nsp.nspname||'"."'||p.proname||'"('||pg_get_function_identity_arguments(p.oid)||') OWNER TO ' || v_new_owner || ';' as a from pg_proc p join pg_namespace nsp ON p.pronamespace = nsp.oid where nsp.nspname = v_schema
    LOOP
        EXECUTE r.a;
    END LOOP;
END$$;

基于@rkj,@ AlannaRose,@ ShachonThomas,@ user3560574和this answer @a_horse_with_no_name

提供的答案

非常感谢。

更好的是:同时更改数据库架构所有者。

DO $$DECLARE r record;
DECLARE
    v_schema varchar := 'public';
    v_new_owner varchar := 'admin_ctes';
BEGIN
    FOR r IN 
        select 'ALTER TABLE "' || table_schema || '"."' || table_name || '" OWNER TO ' || v_new_owner || ';' as a from information_schema.tables where table_schema = v_schema
        union all
        select 'ALTER TABLE "' || sequence_schema || '"."' || sequence_name || '" OWNER TO ' || v_new_owner || ';' as a from information_schema.sequences where sequence_schema = v_schema
        union all
        select 'ALTER TABLE "' || table_schema || '"."' || table_name || '" OWNER TO ' || v_new_owner || ';' as a from information_schema.views where table_schema = v_schema
        union all
        select 'ALTER FUNCTION "'||nsp.nspname||'"."'||p.proname||'"('||pg_get_function_identity_arguments(p.oid)||') OWNER TO ' || v_new_owner || ';' as a from pg_proc p join pg_namespace nsp ON p.pronamespace = nsp.oid where nsp.nspname = v_schema
        union all
        select 'ALTER SCHEMA "' || v_schema || '" OWNER TO ' || v_new_owner 
        union all
        select 'ALTER DATABASE "' || current_database() || '" OWNER TO ' || v_new_owner 
    LOOP
        EXECUTE r.a;
    END LOOP;
END$$;

答案 7 :(得分:16)

非常简单

  1. su - postgres
  2. PSQL
  3. [old_user]重新拥有[new_user];
  4. \ c [您的数据库]
  5. [old_user]重新拥有[new_user];
  6. 进行。

答案 8 :(得分:9)

您可以在PostgreSQL 9

中尝试以下操作
DO $$DECLARE r record;
BEGIN
    FOR r IN SELECT tablename FROM pg_tables WHERE schemaname = 'public'
    LOOP
        EXECUTE 'alter table '|| r.tablename ||' owner to newowner;';
    END LOOP;
END$$;

答案 9 :(得分:7)

PostgreSQL中没有这样的命令。但是你可以使用方法I described解决GRANTs。

答案 10 :(得分:3)

基于answer by elysch,这是一个多模式的解决方案:

DO $$
DECLARE 
  r record;
  i int;
  v_schema text[] := '{public,schema1,schema2,schema3}';
  v_new_owner varchar := 'my_new_owner';
BEGIN
    FOR r IN 
        select 'ALTER TABLE "' || table_schema || '"."' || table_name || '" OWNER TO ' || v_new_owner || ';' as a from information_schema.tables where table_schema = ANY (v_schema)
        union all
        select 'ALTER TABLE "' || sequence_schema || '"."' || sequence_name || '" OWNER TO ' || v_new_owner || ';' as a from information_schema.sequences where sequence_schema = ANY (v_schema)
        union all
        select 'ALTER TABLE "' || table_schema || '"."' || table_name || '" OWNER TO ' || v_new_owner || ';' as a from information_schema.views where table_schema = ANY (v_schema)
        union all
        select 'ALTER FUNCTION "'||nsp.nspname||'"."'||p.proname||'"('||pg_get_function_identity_arguments(p.oid)||') OWNER TO ' || v_new_owner || ';' as a from pg_proc p join pg_namespace nsp ON p.pronamespace = nsp.oid where nsp.nspname = ANY (v_schema)
        union all
        select 'ALTER DATABASE "' || current_database() || '" OWNER TO ' || v_new_owner 
    LOOP
        EXECUTE r.a;
    END LOOP;
    FOR i IN array_lower(v_schema,1) .. array_upper(v_schema,1)
    LOOP
        EXECUTE 'ALTER SCHEMA "' || v_schema[i] || '" OWNER TO ' || v_new_owner ;
    END LOOP;
END
$$;

答案 11 :(得分:2)

我不得不更改表,视图和序列的所有权,发现@rjk发布的出色解决方案可以正常工作-尽管有一个细节: 如果对象名称是大小写混合的(例如“ TableName”),则将失败,并显示“找不到”错误。
为了避免这种情况,请使用“”将对象名称包装起来,如下所示:

表格

SELECT 'ALTER TABLE \"'|| schemaname || '.' || tablename ||'\" OWNER TO my_new_owner;'
FROM pg_tables WHERE NOT schemaname IN ('pg_catalog', 'information_schema')
ORDER BY schemaname, tablename;

序列

SELECT 'ALTER SEQUENCE \"'|| sequence_schema || '.' || sequence_name ||'\" OWNER TO my_new_owner;'
FROM information_schema.sequences WHERE NOT sequence_schema IN ('pg_catalog', 'information_schema')
ORDER BY sequence_schema, sequence_name;

观看次数

SELECT 'ALTER VIEW \"'|| table_schema || '.' || table_name ||'\" OWNER TO my_new_owner;'
FROM information_schema.views WHERE NOT table_schema IN ('pg_catalog', 'information_schema')
ORDER BY table_schema, table_name;

答案 12 :(得分:2)

@Alex Soto的回答是正确的,@ Yoav Aner上传的要点也有效,前提是表/视图名称中没有特殊字符(在postgres中是合法的)。

你需要让他们逃避工作,我已经上传了一个要点:https://gist.github.com/2911117

答案 13 :(得分:1)

我为此创建了一个方便的脚本; pg_change_db_owner.sh。此脚本更改了数据库模式中所有表,视图,序列和函数的所有权,也更改了模式本身的所有者。

请注意,如果您想在特定数据库中更改所有对象的所有权, 由特定数据库角色拥有,然后您只需使用命令REASSIGN OWNED

答案 14 :(得分:1)

与@ AlexSoto的功能方法相同:

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

答案 15 :(得分:1)

以下更简单的shell脚本对我有用。

#!/bin/bash
for i in  `psql -U $1  -qt -c  "select tablename from pg_tables where schemaname='$2'"`
do
psql -U $1 -c  "alter table $2.$i set schema $3"
done

输入$ 1 - 用户名(数据库) $ 2 =现有架构 $ 3 =新架构。

答案 16 :(得分:1)

在解决方案处理所有事情之后,接受的解决方案不会处理功能所有权(在审核时我注意到它与上面的@magiconair类似)

echo "Database: ${DB_NAME}"
echo "Schema: ${SCHEMA}"
echo "User: ${NEW_OWNER}"

pg_dump -s -c -U postgres ${DB_NAME} | egrep "${SCHEMA}\..*OWNER TO"| sed -e "s/OWNER TO.*;$/OWNER TO ${NEW_OWNER};/" | psql -U postgres -d ${DB_NAME}
# do following as last step to allow recovery
psql -U postgres -d postgres -c "ALTER DATABASE ${DB_NAME} OWNER TO ${NEW_OWNER};"

答案 17 :(得分:1)

从PostgreSQL 9.0开始,您可以GRANT [priv name] ON ALL [object type] IN SCHEMA其中[priv name]是典型的SELECT, INSERT, UPDATE, DELETE, etc[object type]可以是以下之一:

  • TABLES
  • SEQUENCES
  • FUNCTIONS

GRANTREVOKE上的PostgreSQL文档详细介绍了这一点。在某些情况下,它仍然需要使用涉及系统目录(pg_catalog.pg_*)的技巧,但它并不常见。我经常做以下事情:

  1. BEGIN修改权限的交易
  2. DATABASES的所有权更改为“DBA角色”
  3. SCHEMAS的所有权更改为“DBA角色”
  4. 来自所有角色的所有REVOKE ALLTABLESSEQUENCES
  5. FUNCTIONS个人
  6. GRANT SELECT, INSERT, UPDATE, DELETE关于适当角色的相关/适当表格
  7. COMMIT DCL交易。

答案 18 :(得分:1)

pg_dump as insert statements 
pg_dump -d -O database filename
-d ( data as inserts ) -O ( capital O is no owner )

然后使用以下命令将备份文件重新导入PostgreSQL:

psql -d database -U username -h hostname < filename

由于没有包含所有者,因此所有创建的表,模式等都是在您指定的登录用户下创建的。

我已经读过这可能是在PostgreSQL版本之间迁移的好方法。

答案 19 :(得分:0)

Docker:修改所有Tables + Sequences的所有者

export user="your_new_owner"
export dbname="your_db_name"

cat <<EOF | docker run -i --rm --link postgres:postgres postgres sh -c "psql -h \$POSTGRES_PORT_5432_TCP_ADDR -p \$POSTGRES_PORT_5432_TCP_PORT -U postgres -d $dbname" | grep ALTER | docker run -i --rm --link postgres:postgres postgres sh -c "psql -h \$POSTGRES_PORT_5432_TCP_ADDR -p \$POSTGRES_PORT_5432_TCP_PORT -U postgres -d $dbname"
SELECT 'ALTER TABLE '||schemaname||'.'||tablename||' OWNER TO $user;' FROM pg_tables WHERE schemaname = 'public';
SELECT 'ALTER SEQUENCE '||relname||' OWNER TO $user;' FROM pg_class WHERE relkind = 'S';
EOF

答案 20 :(得分:0)

对于表格,您必须循环:

for tbl in `psql -qAt -c "select tablename from pg_tables where schemaname = 'public';" YOUR_DB` ; do  psql -U postgres -c "alter table \"$tbl\" owner to NEW_USER" YOUR_DB ; done

答案 21 :(得分:0)

重新分配拥有的对我不起作用,因为我想更改 postgres 拥有的表。

我最终使用了 Alex 的方法,但是我想从 psql 中执行此操作。以下对我来说已经足够了。

DO $$
DECLARE
    rec record;
BEGIN
    FOR rec in 
        SELECT *
        FROM pg_tables
        where schemaname = 'public'
LOOP
    EXECUTE 'alter table ' || quote_ident(rec.tablename) || ' owner to new_owner';
    END LOOP;
END
$$;

答案 22 :(得分:0)

这对 ansible 来说非常简单。您也可以跳过 obj_type 来修改任何对象类型的所有权。

- name: Reassigner owner of all objects
  postgresql_owner:
    login_user: "{{ postgres_admin_username }}"
    login_unix_socket: "{{postgres_socket}}"
    db: "db-name"
    new_owner: "new-owner"
    reassign_owned_by: "old-owner"
    obj_type: "table"

以下是包含更多信息的文档:https://docs.ansible.com/ansible/latest/collections/community/general/postgresql_owner_module.html

希望有所帮助。

答案 23 :(得分:0)

从其他人的讨论来看,这与我自己的问题不一致。如前所述,如果所有者是 postgres,则 REASSIGN OWNED 不起作用。所以,我写了这个脚本,灵感来自之前的讨论:

CREATE OR REPLACE FUNCTION public.alt_own_onall (v_new_owner text)
    RETURNS void
    LANGUAGE plpgsql
AS $alt_own_onall$
-- ALTer OWNer ON ALL objects
DECLARE
    r           RECORD;
    v_sqlcmd    TEXT; -- commande SQL
    b_modif     BOOLEAN DEFAULT false;    -- si au moins une modif
BEGIN
    v_new_owner := quote_ident (v_new_owner);
    IF v_new_owner NOT IN
        (SELECT role_name FROM information_schema.enabled_roles WHERE role_name <>'postgres')
        THEN
            RAISE WARNING '[%] est inconnu', v_new_owner;
            RETURN;
    END IF
    ; -- tables
    RAISE INFO 'Le nouveau propriétaire des tables, vues, fonctions, schémas et de la base va être [%]', v_new_owner
    ;
    FOR r IN
        SELECT quote_ident(schemaname) || '.' || quote_ident(tablename) sch_tbl
        FROM pg_catalog.pg_tables
        WHERE schemaname !~'^(pg_|information)' AND tableowner <> v_new_owner
    LOOP
        v_sqlcmd := 'ALTER TABLE ' || r.sch_tbl || ' OWNER TO ' || v_new_owner || ';';
        RAISE INFO 'Exécution de [%]', v_sqlcmd;
        EXECUTE v_sqlcmd;
        b_modif := true;
    END LOOP
    ; -- views
    FOR r IN
        SELECT quote_ident(schemaname) || '.' || quote_ident(viewname) v_sch_nam
        FROM pg_catalog.pg_views
        WHERE schemaname !~'^(pg_|information)' AND viewowner <> v_new_owner
    LOOP
        v_sqlcmd := 'ALTER VIEW '|| r.v_sch_nam ||' OWNER TO ' || v_new_owner || ';';
        RAISE INFO 'Exécution de [%]', v_sqlcmd;
        EXECUTE v_sqlcmd;
        b_modif := true;
    END LOOP
    ; -- séquences
/*
    ERROR:  cannot change owner of sequence "*_seq"
    DETAIL:  Sequence "*_seq" is linked to table "*".

    FOR r IN
        SELECT quote_ident(sequence_schema) || '.' || quote_ident(sequence_name) s_sch_nam
        FROM information_schema.sequences
        WHERE sequence_schema !~'^(pg_|information)'
    LOOP
        EXECUTE 'ALTER SEQUENCE ' || r.s_sch_nam || ' OWNER TO ' || v_new_owner || ';'
        ;
    END LOOP
    ; -- fonctions */
    FOR r IN
        SELECT
            quote_ident (n.nspname) || '.' || quote_ident (p.proname) || '(' ||
            pg_get_function_identity_arguments (p.oid) || ')' AS nsp_pro_arg
        FROM pg_proc AS p
            JOIN pg_namespace   AS n ON p.pronamespace    = n.oid
            JOIN pg_authid      AS a ON p.proowner        = a.oid
        WHERE n.nspname !~'^(pg_|information)' AND quote_ident(a.rolname) <> v_new_owner
    LOOP
        v_sqlcmd := 'ALTER FUNCTION ' || r.nsp_pro_arg || ' OWNER TO ' || v_new_owner || ';';
        RAISE INFO 'Exécution de [%]', v_sqlcmd;
        EXECUTE v_sqlcmd;
        b_modif := true;
    END LOOP
    ; -- schémas
    FOR r IN
        SELECT quote_ident(schema_name) s_nam
        FROM information_schema.schemata
        WHERE schema_name !~'^(pg_|information)' AND quote_ident(schema_owner) <> v_new_owner
    LOOP
        v_sqlcmd := 'ALTER SCHEMA ' || r.s_nam || ' OWNER TO ' || v_new_owner || ';';
        RAISE INFO 'Exécution de [%]', v_sqlcmd;
        EXECUTE v_sqlcmd;
        b_modif := true;
    END LOOP
    ; -- base
    FOR r IN
        SELECT d.datname, a.rolname
        FROM pg_database d JOIN pg_authid a ON d.datdba=a.oid
        WHERE d.datname=current_database() AND a.rolname <> v_new_owner
    LOOP
        v_sqlcmd := 'ALTER DATABASE ' || quote_ident(current_database()) || ' OWNER TO ' || v_new_owner || ';';
        RAISE INFO 'Exécution de [%]', v_sqlcmd;
        EXECUTE v_sqlcmd;
        b_modif := true;
    END LOOP
    ;
    IF NOT b_modif THEN RAISE INFO 'Aucune modification n''a été effectuée.'; END IF;
END
;$alt_own_onall$;

在 psql 下使用它: SELECT alt_own_onall ('new_role_name'); 您必须将消息从法语翻译成您自己的语言。 适用于 pg 9.5