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

Modify OWNER on all tables simultaneously in PostgreSQL

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

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


您可以使用REASSIGN OWNED命令。

简介:

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

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

它至少可追溯到8.2。他们的在线文档只能追溯到那个时候。


REASSIGN OWNED命令

注意:正如@trygvis在下面的答案中提到的,REASSIGN OWNED命令至少在8.2版之后可用,并且是一种更简单的方法。

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

桌子:

1
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

序列:

1
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

意见:

1
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语句对于这三个语句都是相同的,所以您可能会稍微弄干这一点。


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

桌子

1
2
3
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;

序列

1
2
3
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;

意见

1
2
3
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;

物化视图

基于这个答案

1
2
3
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中检查您的工作,方法是:

1
2
3
\dt *.*
\ds *.*
\dv *.*


如果您希望在一个SQL语句中执行此操作,则需要定义一个exec()函数,如http://wiki.postgresql.org/wiki/dynamic-ddl中所述。

1
2
3
4
5
6
7
CREATE FUNCTION EXEC(text) RETURNS text LANGUAGE plpgsql volatile
  AS $f$
    BEGIN
      EXECUTE $1;
      RETURN $1;
    END;
$f$;

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

1
2
3
4
5
6
7
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新名称。

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

感谢Rodiumtoad对PostgreSQL的帮助。


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

但是,pg_dump允许您只转储模式,其中包含您需要的alter xxx owner to yyy;语句。这是我关于这个话题的一点壳牌魔法

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

很简单,试试看……

1
 SELECT 'ALTER TABLE ' || TABLE_NAME || ' OWNER TO myuser;' FROM information_schema.tables WHERE table_schema = 'public';


很简单

  • 苏格拉底
  • PSQL
  • 将[旧用户]拥有的重新分配给[新用户];
  • C[您的数据库]
  • 将[旧用户]拥有的重新分配给[新用户];
  • 完成。


    我喜欢这个,因为它在一个go(在一个SQL语句中)中修改某个模式的表、视图、序列和函数所有者,而不创建函数,并且您可以直接在pgadmin i i i和psql中使用它:

    (在PostgreSQL V9.2中测试)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    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、@sharoonthomas、@user3560574提供的答案以及@a_horse_(无名称)提供的答案

    非常感谢。

    更好的是:还要更改数据库和模式所有者。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    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$$;


    您可以在PostgreSQL 9中尝试以下操作

    1
    2
    3
    4
    5
    6
    7
    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$$;


    PostgreSQL中没有这样的命令。但是你可以使用我之前描述的方法来解决这个问题。


    根据Elysch的答案,这里有一个针对多个模式的解决方案:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    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
    $$;

    @alex soto给出的答案是正确的,如果表/视图名称中没有特殊字符(Postgres中是合法的),@yoav aner上传的要点也可以工作。

    你需要逃离他们去工作,我已经为此上传了一个gist:https://gist.github.com/2911117


    下面这个简单的shell脚本对我很有用。

    1
    2
    3
    4
    5
    #!/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=新模式。


    我已经为它创建了一个方便的脚本:pg_change_db_owner.sh。这个脚本更改了数据库架构中所有表、视图、序列和函数的所有权,也更改了架构本身的所有者。

    请注意,如果您只想更改特定数据库中所有对象的所有权,由特定的数据库角色拥有,那么您可以简单地使用命令REASSIGN OWNED


    我不得不更改表、视图和序列的所有权,发现@rjk发布的伟大解决方案运行良好-尽管有一个细节:如果对象名是混合大小写的(例如"tablename"),则此操作将失败,并出现"未找到"错误。要绕过此问题,请使用如下所示的""'包装对象名称:

    桌子

    1
    2
    3
    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;

    序列

    1
    2
    3
    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;

    意见

    1
    2
    3
    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;

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

    • TABLES
    • SEQUENCES
    • FUNCTIONS

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

  • BEGIN修改特权的交易
  • DATABASES的所有权改为"DBA角色"
  • SCHEMAS的所有权改为"dba角色"
  • 所有角色的TABLESSEQUENCESFUNCTIONS上的REVOKE ALL特权
  • GRANT SELECT, INSERT, UPDATE, DELETE关于适当角色的相关/适当表格
  • COMMITDCL交易。

  • 1
    2
    3
    pg_dump AS INSERT statements
    pg_dump -d -O DATABASE filename
    -d ( DATA AS inserts ) -O ( capital O IS no owner )

    然后使用以下命令将备份文件传回PostgreSQL:

    1
    psql -d DATABASE -U username -h hostname < filename

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

    我已经读过了,这也是在PostgreSQL版本之间迁移的一个好方法。


    与@alexsoto的函数方法相同:

    1
    2
    3
    IFS=$'
    '
     
    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

    接受的解决方案不处理函数所有权,以下解决方案处理所有问题(回顾时,我注意到它类似于上面的@magiconair)

    1
    2
    3
    4
    5
    6
    7
    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};"


    Docker:修改所有表的所有者+序列

    1
    2
    3
    4
    5
    6
    7
    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