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


409

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

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

Answers:


459

REASSIGN OWNED命令

注意:如@trygvis 在下面的答案中所述,该REASSIGN 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语句对所有三个相同。



10
+1感谢Alex。我根据您的回答创建了一个小bash脚本,可在gist.github.com/2482969上找到
gingerlime 2012年

10
请参阅@trygvis的最新答案。到目前为止,最简单的答案是:REASSIGN OWNED BY old_role [, ...] TO new_role
David

64
REASSIGN OWNED BY不适用于postgres拥有的对象。
BrunoJCM

19
同样,REASSIGN OWNED实际上会影响旧角色拥有的所有数据库的所有权(请参阅:postgresql.org/docs/9.3/static/sql-reassign-owned.html)。因此,如果您只想更改单个数据库的所有权,请当心!
kitsune 2014年

3
基于@gingerlime脚本,bspkrs(找不到他的名字)创建了一个也会更改功能的
脚本

537

您可以使用该REASSIGN OWNED命令。

概要:

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

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

至少可以恢复到8.2。他们的在线文档可以追溯到很久以前。


ERROR: unexpected classid 3079。我想如果有任何扩展名,当前是行不通的。
史蒂夫·乔根森

40
即使我连接到我创建的数据库(即不是系统数据库),这似乎也不适合用户postgres,但它表示:错误:由于数据库需要这些角色,因此无法重新分配角色postgres拥有的对象的所有权系统
thnee

13
正如@thnee报道的那样,REASSIGN会影响数据库中的所有对象,并且不会区分用户定义的对象和系统对象,因此,如果有任何扩展拥有自己的表,则它不适用于postgres。我还是比较喜欢(+1)这个选项,尽管它对我没有多大帮助(我的数据库以前由postgres拥有),但对我没有多大帮助。
Pavel V.

6
为了清楚起见,此命令仅在您当前连接的数据库中有效。如果old_role在多个数据库中拥有对象,则应在每个数据库中连接并运行此命令
mavroprovato

11
这似乎不适用于通过AWS RDS托管的postgres。我收到此错误“拒绝重新分配对象的权限”,并且此链接建议原因:“似乎“重新拥有”的唯一方法是作为超级用户(与文档相抵触),这是无法访问的在RDS中。” postgresql-archive.org/…–
typoerrpr

196

这是: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;

物化视图

根据这个答案

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。我做错了什么?
Tyrone Moodley 2015年

1
我更喜欢这样做,因为它一经登录即可在plsql中运行-Unix级别的脚本(当前最喜欢的答案)在我的环境中要求输入“ -U postgres”和密码。
Dazed

2
我更喜欢这个答案,因为(1)可以在psql或pgAdmin中完成(2)它可以轻松地让您看到将要更改的对象。我还使用了stackoverflow.com/questions/22803096/…,该函数与之相似,但用于功能。
AlannaRose

灿烂的逻辑。
Emipro Technologies Pvt。公司

42

如果要在一个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对此提供了帮助。


2
这会更加有用,因为它会更改整个模式的所有权,包括功能,索引,序列等。谢谢!
liviucmg 2011年

它不会更改架构所有者。还如何更改架构所有者?
安德鲁斯(Andrus)2012年

@Andrus ALTER DATABASE $ DB所有者到$ OWNER;
约翰·达林

alter database更改整个数据库所有者。我问如何更改架构所有者。
Andrus 2014年

阿尔特·希玛(ALTER SCHEMA)将所有者弗雷德(OWNER)告别
埃里克·阿尔丁格

21

最近,我不得不更改数据库中所有对象的所有权。尽管表,视图,触发器和序列在某种程度上很容易更改,但是上述方法对于函数来说是失败的,因为签名是函数名称的一部分。当然,我有MySQL背景并且对Postgres不太熟悉。

但是,pg_dump允许您仅转储模式,其中包含ALTER xxx OWNER TO yyy;。您需要的陈述。这是我关于该主题的一些技巧

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很好用,尤其是因为无论如何您都指定不区分大小写的匹配。
博博特

19

非常简单,尝试一下...

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

4
您可能会添加一条注释,指出必须复制并执行相应的字符串。并不是说它不是很明显:p
Nightscape

其中包括删除alter语句周围的所有引号。在这种情况下,多光标或replace帮助。
已知的2014年


16

我这样的之一,因为它修改视图序列功能有一定的所有者架构一个去(在一个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的答案

非常感谢。


更妙的是:还更改数据库架构所有者。

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不添加这个,我不知道!
PIP

两个问题:1)看起来第一和第三条“ ALTER TABLE”行是重复的。这是故意的(例如,您必须对表进行两次传递以更改所有权吗?)。2)我们发现information_schema.sequences即使SELECT c.* FROM pg_class c WHERE c.relkind = 'S';列出序列也为空。为什么它们不匹配?
GuyPaddock

另外,第二个ALTER查询不应该是ALTER SEQUENCE吗?
GuyPaddock

12

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

6

PostgreSQL中没有这样的命令。但是您可以使用我之前为GRANTs 描述的方法来解决它。


谢谢,不错的文章。我将保留它作为将来的参考。使用pgAdmin,我最终备份了数据库,删除/删除了数据库,临时授予new_owner必要的权限,然后重新创建数据库并将其恢复为new_owner,并在还原窗口中选中了“ no owner”选项。这产生了我在new_owner作为所有内容所有者的情况下寻找的结果。

Postgres 9.3引入了REASSIGN OWNED命令。 postgresql.org/docs/9.3/sql-reassign-owned.html
Georg Zimmer

3

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


2
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版本之间迁移的好方法。


2

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

请注意,如果您只想更改特定数据库角色拥有的特定数据库中所有对象的所有权,则可以简单地使用command REASSIGN OWNED代替。


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

PostgreSQL的文档,GRANTREVOKE继续对此进行更详细的介绍。在某些情况下,仍然需要使用涉及系统目录(pg_catalog.pg_*)的技巧,但这并不普遍。我经常执行以下操作:

  1. BEGIN 修改特权的交易
  2. 将所有权更改DATABASES为“ DBA角色”
  3. 将所有权更改SCHEMAS为“ DBA角色”
  4. REVOKE ALL所有人TABLESSEQUENCES以及FUNCTIONS所有角色
  5. GRANT SELECT, INSERT, UPDATE, DELETE 在相关/适当的表上扮演适当的角色
  6. COMMIT DCL交易。

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};"

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 =新模式。


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

0

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
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.