MyTetra Share
Делитесь знаниями!
Modify OWNER on all tables simultaneously in PostgreSQL
Время создания: 13.07.2018 15:30
Текстовые метки: postgresql
Раздел: Postgresql
Запись: Velonski/mytetra-database/master/base/15269175809ffv88suaj/text.html на raw.githubusercontent.com

How do I modify the owner of all tables in a PostgreSQL database?


I tried ALTER TABLE * OWNER TO new_owner but it doesn't support the asterisk syntax.


postgresql

shareimprove this question

edited Feb 5 '14 at 19:54


newUserNameHere

6,571113260

asked Aug 28 '09 at 16:32


Kai

4,68352128

add a comment

19 Answers

active oldest votes

up vote

378

down vote

accepted

See REASSIGN OWNED command

Note: As @trygvis mentions in the answer below, the REASSIGN OWNED command is available since at least version 8.2, and is a much easier method.


Since you're changing the ownership for all tables, you likely want views and sequences too. Here's what I did:


Tables:


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

Sequences:


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

Views:


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

You could probably DRY that up a bit since the alter statements are identical for all three.


shareimprove this answer

edited Oct 2 '17 at 11:45


Janusz Skonieczny

6,52273349

answered Apr 21 '10 at 20:05


Alex Soto

4,4031147

9

+1 Thanks Alex. I've created a little bash script based on your answer, available at gist.github.com/2482969 – gingerlime Apr 24 '12 at 19:33

9

See the recent answer by @trygvis. Simplest answer by far: REASSIGN OWNED BY old_role [, ...] TO new_role – David Dec 4 '12 at 23:39

47

REASSIGN OWNED BY doesn't work for objects owned by postgres. – BrunoJCM Apr 1 '13 at 17:31

14

Also, REASSIGN OWNED actually affects the ownership of all databases owned by the old role (See: postgresql.org/docs/9.3/static/sql-reassign-owned.html). So if you only want to change the ownership of a single database, beware! – kitsune Oct 31 '14 at 14:24

2

Based on @gingerlime script, bspkrs (couldn't find his name) created one that also changes the functions: https://gist.github.com/bspkrs/b997ed7f1eb1268f3403 – elysch May 16 '16 at 15:15

show 6 more comments

up vote

453

down vote

You can use the REASSIGN OWNED command.


Synopsis:

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

This changes all objects owned by old_role to the new role. You don't have to think about what kind of objects that the user has, they will all be changed. Note that it only applies to objects inside a single database. It does not alter the owner of the database itself either.


It is available back to at least 8.2. Their online documentation only goes that far back.


shareimprove this answer

edited Dec 5 '12 at 12:55


Konrad Garus

36.4k31126200

answered Nov 23 '12 at 20:09


Trygve Laugstøl

5,36322737

This works exactly as you imagine. Perfect and thanks. – Justin Van Horne Dec 21 '12 at 6:37

17

WAY better solution. This should be the accepted answer – vicTROLLA Feb 16 '13 at 22:42

27

This doesnt seem to work for user postgres, even though I am connected to a database that I created (i.e. not a system database), it says this: ERROR: cannot reassign ownership of objects owned by role postgres because they are required by the database system – thnee Mar 8 '13 at 23:19

12

As @thnee reported, REASSIGN affects all objects in the database and it doesn't discriminate between user defined and system objects, so it doesn't work for postgres if there are any extension having their own tables. Still I prefer (+1) this option for elegance, even though it didn't help me much (my database was previously owned by postgres). – Pavel V. Jul 3 '14 at 6:21

2

Just to be clear, this command works in the database that you are currently connected ONLY. If the old_role owns objects in multiple databases, you should connect and run this command in each one of those databases – mavroprovato Jul 7 '16 at 9:08

show 3 more comments

up vote

143

down vote

This: http://archives.postgresql.org/pgsql-bugs/2007-10/msg00234.php is also a nice and fast solution, and works for multiple schemas in one database:


Tables


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;

Sequences


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;

Views


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;

Materialized Views


Based on this answer


SELECT 'ALTER TABLE '|| oid::regclass::text ||' OWNER TO my_new_owner;'

FROM pg_class WHERE relkind = 'm'

ORDER BY oid;

This generates all the required ALTER TABLE / ALTER SEQUENCE / ALTER VIEW statements, copy these and paste them back into plsql to run them.


Check your work in psql by doing:


\dt *.*

\ds *.*

\dv *.*

shareimprove this answer

edited May 23 '17 at 11:55


Community♦

11

answered Jul 8 '11 at 12:27


rkj

4,85722030

3

A very nice solution! – jb. May 24 '12 at 17:10

1

Best in all. This worked a treat mate. – Makky Mar 25 '13 at 13:40

Great solution. My only issue was that I had export the scripts and then execute the exported scripts. I am SQL Server Guru but I am not sure what the shortcut is to execute. I clicked execute query and execute pgScript. What was I doing wrong? – Tyrone Moodley Apr 11 '15 at 12:46

I preferred this as it works from within plsql once logged in - the unix level scripts (currently favourite answer) require a "-U postgres" and password entry in my environment. – Dazed Apr 30 '15 at 8:57

2

I prefer this answer because (1) it can be done in psql or pgAdmin (2) it easily allows you to see the objects you'll be altering. I also used stackoverflow.com/questions/22803096/…, which is similar, but for functions. – AlannaRose Jun 29 '15 at 21:33

show 1 more comment

up vote

38

down vote

If you want to do it in one sql statement, you need to define an exec() function as mentioned in 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$;

Then you can execute this query, it will change the owner of tables, sequences and views:


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 is the postgresql new name of the new owner.


In most circumstances you need to be superuser to execute this. You can avoid that by changing the owner from your own user to a role group you are a member of.


Thanks to RhodiumToad on #postgresql for helping out with this.


shareimprove this answer

edited Apr 2 '12 at 14:11

answered Jul 27 '11 at 23:33


Johan Dahlin

13.4k53050

1

This is much more useful since it changes ownership of the entire schema, including functions, indexes, sequences, etc.. Thank you! – liviucmg Oct 31 '11 at 20:18

It does not change schema owners. How to change schema owners also? – Andrus Jul 30 '12 at 14:46

@Andrus ALTER DATABASE $DB OWNER TO $OWNER; – Johan Dahlin Jul 31 '12 at 19:04

alter database changes whole database owner. I asked how to change schema owners. – Andrus Jun 20 '14 at 20:01

ALTER SCHEMA fred OWNER TO betty; – Eric Aldinger Apr 16 at 21:41

add a comment

up vote

17

down vote

I recently had to change the ownership of all objects in a database. Although tables, views, triggers and sequences were somewhat easily changed the above approach failed for functions as the signature is part of the function name. Granted, I have a MySQL background and am not that familiar with Postgres.


However, pg_dump allows you to dump just the schema and this contains the ALTER xxx OWNER TO yyy; statements you need. Here is my bit of shell magic on the topic


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

shareimprove this answer

answered Aug 21 '10 at 1:29


magiconair

2,36132026

add a comment

up vote

15

down vote

very simple, try it...


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

shareimprove this answer

answered Feb 6 '13 at 13:02


mwendamseke

18915

4

You might add a note that the corresponding strings have to be copied and executed. Not that it's not obvious :p – Nightscape May 13 '13 at 13:55

Which includes removing all the quotes around the alter statements.. multi-cursors or replace helps in this case. – knownasilya Oct 13 '14 at 13:31

add a comment

up vote

12

down vote

is very simple


su - postgres

psql

REASSIGN OWNED BY [old_user] TO [new_user];

\c [your database]

REASSIGN OWNED BY [old_user] TO [new_user];

done.


shareimprove this answer

answered Apr 11 '16 at 2:40


durenzo

12112

1

This probably does what the querent wanted. By far the easiest. – Geof Sawaya Feb 10 '17 at 10:55

You're only 4 years late to the party; scroll up: stackoverflow.com/a/13535184/1772379 – Ben Johnson Dec 5 '17 at 14:53

add a comment

up vote

12

down vote

I like this one since it modifies tables, views, sequences and functions owner of a certain schema in one go (in one sql statement), without creating a function and you can use it directly in PgAdmin III and psql:


(Tested in 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$$;

Based on answers provided by @rkj, @AlannaRose, @SharoonThomas, @user3560574 and this answer by @a_horse_with_no_name


Thank's a lot.


Better yet: Also change database and schema owner.


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

shareimprove this answer

edited May 23 '17 at 11:47


Community♦

11

answered May 16 '16 at 17:22


elysch

93621430

AMAZING! Why postgres does not add this I do not know! – pip May 20 '16 at 12:51

Two questions: 1) It looks like the first and third "ALTER TABLE" lines are dupes. Is that intentional (e.g. do you have to do two passes over the tables to change ownership?). 2) We're finding that information_schema.sequences is empty even though SELECT c.* FROM pg_class c WHERE c.relkind = 'S'; lists sequences. Why might they not match? – GuyPaddock Sep 13 '17 at 18:27

Also, shouldn't the second ALTER query be an ALTER SEQUENCE? – GuyPaddock Sep 13 '17 at 18:34

add a comment

up vote

9

down vote

You can try the following in 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$$;

shareimprove this answer

answered Apr 22 '14 at 13:07


user3560574

9111

add a comment

up vote

7

down vote

There is no such command in PostgreSQL. But you can work around it using method I described some time ago for GRANTs.


shareimprove this answer

answered Aug 28 '09 at 16:50

user80168

Thank you, very nice article. I will keep this as a future reference. Using pgAdmin, I ended up backing up the DB, dropping/deleting the DB, temporarily granting new_owner the necessary rights, and then re-creating and restoring DB as the new_owner, with the "no owner" option checked in the restore window. This produced the results I was looking for with new_owner as the owner of everything. – Kai Aug 28 '09 at 18:23

add a comment

up vote

3

down vote

Based on the answer by elysch, here is a solution for multiple schemas:


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

$$;

shareimprove this answer

edited May 23 '17 at 12:18


Community♦

11

answered Jun 9 '16 at 9:05


JC Boggio

1105

add a comment

up vote

2

down vote

The answer by @Alex Soto is the right one and the gist uploaded by @Yoav Aner also works provided there are no special characters in the table/view names (which are legal in postgres).


You need to escape them to work and I have uploaded a gist for that: https://gist.github.com/2911117


shareimprove this answer

answered Jun 15 '12 at 5:46


Sharoon Thomas

1,2111212

add a comment

up vote

1

down vote

Starting in PostgreSQL 9.0, you have the ability to GRANT [priv name] ON ALL [object type] IN SCHEMA where [priv name] is the typical SELECT, INSERT, UPDATE, DELETE, etc and [object type] can be one of:


TABLES

SEQUENCES

FUNCTIONS

PostgreSQL's docs on GRANT and REVOKE go in to more detail regarding this. In some situations it's still required to use tricks involving the system catalogs (pg_catalog.pg_*) but it's not nearly as common. I frequently do the following:


BEGIN a transaction to modify the privs

Change ownership of DATABASES to a "DBA role"

Change ownership of SCHEMAS to the "DBA role"

REVOKE ALL privs on all TABLES, SEQUENCES and FUNCTIONS from all roles

GRANT SELECT, INSERT, UPDATE, DELETE on relevant/appropriate tables to the appropriate roles

COMMIT the DCL transaction.

shareimprove this answer

answered Feb 9 '12 at 17:11


Sean

7,44632838

add a comment

up vote

1

down vote

pg_dump as insert statements

pg_dump -d -O database filename

-d ( data as inserts ) -O ( capital O is no owner )

Then pipe the backup file back in to PostgreSQL using:


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

As there is no owner included then all of the created table, schema, etc, are created under the login user you specify.


I have read this could be a good approach for migrating between PostgreSQL versions as well.


shareimprove this answer

edited Sep 14 '12 at 10:48


Sicco

4,60933251

answered Dec 5 '10 at 20:02


atwsKris

115

add a comment

up vote

1

down vote

The accepted solution does not take care of function ownership following solution takes care of everything (while reviewing I noticed that it is similar to @magiconair above)


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

shareimprove this answer

answered Oct 7 '12 at 20:58


jsh

11110

add a comment

up vote

1

down vote

I’ve created a convenient script for that; pg_change_db_owner.sh. This script change ownership for all tables, views, sequences and functions in a database schema and also owner of the schema itself.


Please note that if you wanna just change the ownership of all objects, in a particular database, owned by a particular database role, then you can simply use command REASSIGN OWNED instead.


shareimprove this answer

answered Aug 14 '14 at 20:42


Jakub Jirutka

5,45122530

Works great for me. This is what many would be looking for. – Chand Prakash Nov 13 '15 at 11:36

add a comment

up vote

1

down vote

The following simpler shell script worked for me.


#!/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

Where input $1 - username (database) $2 = existing schema $3 = to new schema.


shareimprove this answer

edited Feb 19 '15 at 21:57


Brad Koch

9,5491271103

answered Dec 8 '14 at 10:46


sramay

18113

add a comment

up vote

1

down vote

Same as @AlexSoto's approach for functions:


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

shareimprove this answer

answered Sep 6 '17 at 9:49


Anton Smolkov

111

add a comment

up vote

0

down vote

Docker: Modify Owner of all 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

Так же в этом разделе:
 
MyTetra Share v.0.59
Яндекс индекс цитирования