【问题标题】:PostgreSQL: Modify OWNER on all tables simultaneously in PostgreSQLPostgreSQL:在 PostgreSQL 中同时修改所有表的 OWNER
【发布时间】:2010-11-23 19:17:30
【问题描述】:

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

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

【问题讨论】:

    标签: postgresql


    【解决方案1】:

    您可以使用REASSIGN OWNED 命令。

    简介:

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

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

    至少可以回溯到 8.2。他们的在线文档只能追溯到那么远。

    【讨论】:

    • 这似乎不适用于用户 postgres,即使我连接到我创建的数据库(即不是系统数据库),它也会显示:错误:无法重新分配角色拥有的对象的所有权postgres,因为它们是数据库系统所需要的
    • 听起来您正在尝试重新分配 postgresql 内部对象的所有权,例如 pg_* 表/视图。
    • 正如@thnee 报告的那样,REASSIGN 会影响数据库中的所有对象,并且它不区分用户定义对象和系统对象,因此如果有任何扩展拥有自己的表,则它不适用于 postgres .我仍然更喜欢(+1)这个优雅的选项,尽管它对我没有多大帮助(我的数据库以前归 postgres 所有)。
    • 为了清楚起见,此命令仅适用于您当前连接的数据库。如果 old_role 拥有多个数据库中的对象,您应该在每个数据库中连接并运行此命令
    • 这似乎不适用于通过 AWS RDS 托管的 postgres。我收到此错误“重新分配对象的权限被拒绝”,此链接说明了原因:“看来,'重新分配拥有'的唯一方法是作为超级用户(这与文档相矛盾),这是不可访问的在 RDS 中。 postgresql-archive.org/…
    【解决方案2】:

    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
    

    您可能会DRY 稍微提高一点,因为所有三个的 alter 语句都是相同的。


    【讨论】:

    • +1 谢谢亚历克斯。我根据您的回答创建了一个小 bash 脚本,可在 gist.github.com/2482969 找到
    • 查看@trygvis 最近的回答。迄今为止最简单的答案:REASSIGN OWNED BY old_role [, ...] TO new_role
    • REASSIGN OWNED BY 不适用于 postgres 拥有的对象。
    • 另外,REASSIGN OWNED 实际上会影响旧角色拥有的所有数据库的所有权(请参阅:postgresql.org/docs/9.3/static/sql-reassign-owned.html)。因此,如果您只想更改单个数据库的所有权,请注意!
    • 基于@gingerlime 脚本,bspkrs(找不到他的名字)创建了一个也改变了功能:https://gist.github.com/bspkrs/b997ed7f1eb1268f3403
    【解决方案3】:

    这: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 *.*
    

    【讨论】:

    • 很好的解决方案。我唯一的问题是我导出了脚本,然后执行了导出的脚本。我是 SQL Server Guru,但我不确定要执行的快捷方式是什么。我单击执行查询并执行 pgScript。我做错了什么?
    • 我更喜欢这个,因为一旦登录它就可以在 plsql 中工作 - unix 级脚本(目前最喜欢的答案)需要在我的环境中输入“-U postgres”和密码。
    • 我更喜欢这个答案,因为 (1) 它可以在 psql 或 pgAdmin 中完成 (2) 它很容易让您看到您将要更改的对象。我也使用了stackoverflow.com/questions/22803096/…,类似,但用于功能。
    • 逻辑精彩。
    • 可以用这种方式在sql中执行。 stackoverflow.com/questions/31847819/…
    【解决方案4】:

    如果你想在一个sql语句中完成,你需要定义一个exec()函数,如http://wiki.postgresql.org/wiki/Dynamic_DDL中提到的那样

    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 新名称。

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

    感谢 #postgresql 上的 RhodiumToad 提供帮助。

    【讨论】:

    • 这更有用,因为它改变了整个架构的所有权,包括函数、索引、序列等。谢谢!
    • 它不会更改架构所有者。如何也更改架构所有者?
    • @Andrus 将数据库 $DB 所有者更改为 $OWNER;
    • alter database 更改整个数据库所有者。我问如何更改架构所有者。
    • 将模式弗雷德所有者更改为贝蒂;
    【解决方案5】:

    很简单

    1. su - postgres
    2. psql
    3. REASSIGN OWNED BY [old_user] TO [new_user];
    4. \c [your database]
    5. REASSIGN OWNED BY [old_user] TO [new_user];

    完成。

    【讨论】:

    • 可能做了询问者想要的。到目前为止最简单的。
    • 你只迟到了 4 年;向上滚动:stackoverflow.com/a/13535184/1772379
    • @BenJohnson 在这个答案中并没有解释如何使用它:/
    【解决方案6】:

    我喜欢这个,因为它修改了某个表格视图序列函数的所有者一次性中的strong>schema(在一条sql语句中),无需创建函数,您可以直接在PgAdmin IIIpsql:

    (在 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、@SharoonThomas、@user3560574 和 @a_horse_with_no_name 提供的答案

    非常感谢。


    更好:同时更改 databaseschema 所有者。

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

    【讨论】:

    • 太棒了!为什么postgres不添加这个我不知道!
    • 两个问题:1)看起来第一行和第三行“ALTER TABLE”是骗子。这是故意的(例如,您是否必须两次通过表才能更改所有权?)。 2) 我们发现information_schema.sequences 是空的,即使SELECT c.* FROM pg_class c WHERE c.relkind = 'S'; 列出了序列。为什么它们可能不匹配?
    • 另外,第二个ALTER查询不应该是ALTER SEQUENCE吗?
    • 为什么要通过 alter table 命令更新序列所有者?
    【解决方案7】:

    我最近不得不更改数据库中所有对象的所有权。尽管表、视图、触发器和序列在某种程度上很容易更改,但上述方法对于函数失败了,因为签名是函数名称的一部分。当然,我有 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
    

    【讨论】:

    • 我不确定您为什么使用grep 命令。我自己是 Linux 新手,但据我了解,sed 似乎很好用,尤其是因为您指定了不区分大小写的匹配。
    • grep 在这里用于过滤 pg_dump 的输出,使其仅包含带有 'owner to' 的行,然后使用 sed 对其进行修改。只有带有 'owner to' 的行将被执行,而不是整个转储。
    【解决方案8】:

    很简单,试试吧……

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

    【讨论】:

    • 您可能会添加一个注释,即必须复制和执行相应的字符串。并不是说它不明显:p
    • 这包括删除alter语句周围的所有引号。在这种情况下,多光标或替换有帮助。
    • 在命令末尾添加\gexec 对我有用select 'ALTER TABLE ' || table_name || ' OWNER TO myuser;' from information_schema.tables where table_schema = 'public' \gexec
    【解决方案9】:

    我不得不更改表、视图和序列的所有权,并发现 @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;
    

    【讨论】:

      【解决方案10】:

      您可以在 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$$;
      

      【讨论】:

        【解决方案11】:

        如果当前所有者不是 postgres,你可以使用这个:

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

        但如果当前所有者是 postgres,你肯定会得到错误,所以你必须使用 @dvanrensburg 答案,但如果你想在同一个 sql 中执行命令,请根据需要使用这些命令:

        数据库

        ALTER DATABASE target_database OWNER TO new_onwer;
        

        表格

        DO
        LANGUAGE plpgsql
        $$
        DECLARE
          stmt text;
        BEGIN
          FOR stmt IN
            WITH temp as (
            SELECT 'ALTER TABLE '|| schemaname || '."' || tablename ||'" OWNER TO newuser' as command
            FROM pg_tables WHERE NOT schemaname IN ('pg_catalog', 'information_schema')
            ORDER BY schemaname, tablename )
            SELECT command from temp
          LOOP
            EXECUTE stmt;
          END LOOP;
        END;
        $$;
        

        序列

        DO
        LANGUAGE plpgsql
        $$
        DECLARE
          stmt text;
        BEGIN
          FOR stmt IN
            WITH temp as (
            SELECT 'ALTER SEQUENCE '|| sequence_schema || '."' || sequence_name ||'" OWNER TO newuser;' as command
            FROM information_schema.sequences WHERE NOT sequence_schema IN ('pg_catalog', 'information_schema')
            ORDER BY sequence_schema, sequence_name)
            select command from temp
          LOOP
            EXECUTE stmt;
          END LOOP;
        END;
        $$;
        

        观看次数

        DO
        LANGUAGE plpgsql
        $$
        DECLARE
          stmt text;
        BEGIN
          FOR stmt IN
            WITH temp as (
            SELECT 'ALTER VIEW '|| table_schema || '."' || table_name ||'" OWNER TO newuser;' as command
            FROM information_schema.views WHERE NOT table_schema IN ('pg_catalog', 'information_schema')
            ORDER BY table_schema, table_name)
            select command from temp
          LOOP
            EXECUTE stmt;
          END LOOP;
        END;
        $$;
        

        架构

        DO
        LANGUAGE plpgsql
        $$
        DECLARE
          stmt text;
        BEGIN
          FOR stmt IN
            WITH schema_names as(
            SELECT distinct(schemaname) FROM pg_tables WHERE NOT schemaname IN ('pg_catalog', 'information_schema')
            ORDER BY schemaname)
            SELECT 'ALTER SCHEMA '|| schemaname ||' OWNER TO newuser;' as command
            FROM schema_names
          LOOP
            EXECUTE stmt;
          END LOOP;
        END;
        $$;
        

        还要注意可能需要更改成员资格的数据库的功能和其他组件

        函数和触发函数

            DO
            LANGUAGE plpgsql
            $$
            DECLARE
              stmt text;
            BEGIN
              FOR stmt IN
                WITH temp as(
                SELECT 'alter function '||nsp.nspname||'.'||p.proname||'('||pg_get_function_identity_arguments(p.oid)||') owner to newuser;' as command
                FROM pg_proc p
                JOIN pg_namespace nsp ON p.pronamespace = nsp.oid
                WHERE NOT  nsp.nspname IN ('pg_catalog', 'information_schema'))
                SELECT command FROM temp
              LOOP
                EXECUTE stmt;
              END LOOP;
            END;
            $$;
        

        【讨论】:

        • 谢谢!这是真正的即用型代码
        【解决方案12】:

        PostgreSQL 中没有这样的命令。但是您可以使用方法 I described 一段时间前的 GRANT 来解决它。

        【讨论】:

        • 谢谢,非常好的文章。我将保留此作为将来的参考。使用 pgAdmin,我最终备份了数据库,删除/删除了数据库,暂时授予 new_owner 必要的权限,然后重新创建和还原数据库作为 new_owner,并在还原窗口中选中“无所有者”选项。这产生了我一直在寻找的结果,将 new_owner 作为所有内容的所有者。
        • Postgres 9.3 引入了 REASSIGN OWNED 命令。 postgresql.org/docs/9.3/sql-reassign-owned.html
        【解决方案13】:

        基于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
        $$;
        

        【讨论】:

          【解决方案14】:

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

          你需要避开它们才能工作,我为此上传了一个要点:https://gist.github.com/2911117

          【讨论】:

            【解决方案15】:
            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 版本之间迁移的好方法。

            【讨论】:

            • 我认为如果数据库足够小并且可以选择转储/恢复,这是更改数据库中所有内容所有权的最简单方法。但是pg_dump 命令语法已经过时,-d 现在是--column-inserts,但不建议仅用于 pgsql 操作。我只使用--clean--no-owner
            【解决方案16】:

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

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

            【讨论】:

              【解决方案17】:

              从 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_*) 的技巧,但这并不常见。我经常做以下事情:

              1. BEGIN 修改权限的交易
              2. DATABASES 的所有权更改为“DBA 角色”
              3. SCHEMAS 的所有权更改为“DBA 角色”
              4. REVOKE ALL 所有角色的所有TABLESSEQUENCESFUNCTIONS 的权限
              5. GRANT SELECT, INSERT, UPDATE, DELETE 在相关/适当的表格上分配给适当的角色
              6. COMMIT DCL 交易。

              【讨论】:

                【解决方案18】:

                接受的解决方案不关心函数所有权,下面的解决方案负责一切(回顾时我注意到它类似于上面的@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};"
                

                【讨论】:

                  【解决方案19】:

                  以下更简单的 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 = 新架构。

                  【讨论】:

                    【解决方案20】:

                    与@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
                    

                    【讨论】:

                      【解决方案21】:

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

                      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
                      

                      【讨论】:

                        【解决方案22】:

                        对于表格,您必须循环:

                        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
                        

                        【讨论】:

                          【解决方案23】:

                          重新分配拥有的对我不起作用,因为我想更改 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
                          $$;
                          

                          【讨论】:

                            【解决方案24】:

                            这对于 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

                            希望对您有所帮助。

                            【讨论】:

                              【解决方案25】:

                              从其他人的讨论中,我不同意我自己的问题。如前所述,如果所有者是 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 下使用它: 选择 alt_own_onall ('new_role_name'); 您必须将消息从法语翻译成您自己的语言。 适用于第 9.5 页

                              【讨论】:

                                【解决方案26】:

                                虽然下面没有改变所有者,但改变了角色,这是我需要做的,在搜索谷歌时我最终找到了这个问题,所以为了完整起见,我将在这里输入:

                                对我来说,上述解决方案均无效,我不断收到:must be owner of relation xxx。最终的解决方案是:

                                GRANT olduser TO newuser;

                                【讨论】:

                                • 使用此命令,您不会更改表的所有者。相反,您将 newuser 的角色更改为“olduser”。
                                • @Teodoro,谢谢你的解释,我已经更新了我的答案。
                                猜你喜欢
                                • 2016-05-25
                                • 2020-01-17
                                • 1970-01-01
                                • 1970-01-01
                                • 2019-01-27
                                • 1970-01-01
                                • 2011-01-17
                                • 2018-01-06
                                • 1970-01-01
                                相关资源
                                最近更新 更多