web-dev-qa-db-fra.com

Modifier simultanément OWNER sur toutes les tables dans PostgreSQL

Comment modifier le propriétaire de toutes les tables d'une base de données PostgreSQL?

J'ai essayé ALTER TABLE * OWNER TO new_owner mais il ne supporte pas la syntaxe astérisque.

381
Kai

Voir REASSIGN OWNED commande

Remarque: Comme @trygvis mentionne dans la réponse ci-dessous , le REASSIGN OWNED commande est disponible depuis au moins la version 8.2, et est une méthode beaucoup plus simple.


Puisque vous modifiez la propriété de toutes les tables, vous voudrez probablement aussi des vues et des séquences. Voici ce que j'ai fait:

Les 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
_

Séquences:

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

Vues:

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

Vous pourriez probablement DRY cela un peu, car les instructions alter sont identiques pour les trois.


431
Alex Soto

Vous pouvez utiliser la commande REASSIGN OWNED .

Synopsis:

_REASSIGN OWNED BY old_role [, ...] TO new_role
_

Cela modifie tous les objets appartenant à _old_role_ en nouveau rôle. Vous n'avez pas à penser au type d'objets que possède l'utilisateur, ils seront tous modifiés. Notez que cela ne s'applique qu'aux objets d'une même base de données. Cela ne modifie pas non plus le propriétaire de la base de données.

Il est disponible depuis au moins 8,2. Leur documentation en ligne ne remonte que très loin.

507
Trygve Laugstøl

This: http://archives.postgresql.org/pgsql-bugs/2007-10/msg00234.php est également une solution simple et rapide, qui fonctionne pour plusieurs schémas dans une base de données:

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;

Séquences

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;

Vues

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;

Vues matérialisées

Basé sur cette réponse

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

Cela génère toutes les instructions ALTER TABLE/ALTER SEQUENCE/ALTER VIEW requises, copiez-les et collez-les dans plsql pour les exécuter.

Vérifiez votre travail dans psql en faisant:

\dt *.*
\ds *.*
\dv *.*
176
rkj

Si vous voulez le faire dans une instruction SQL, vous devez définir une fonction exec () comme indiqué dans 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$;

Ensuite, vous pouvez exécuter cette requête, cela changera le propriétaire des tables, des séquences et des vues:

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 est le nouveau nom postgresql du nouveau propriétaire.

Dans la plupart des cas, vous devez être superutilisateur pour l'exécuter. Vous pouvez éviter cela en remplaçant le propriétaire de votre propre utilisateur par un groupe de rôles dont vous êtes membre.

Merci à RhodiumToad sur # postgresql pour son aide.

40
Johan Dahlin

J'ai récemment dû changer la propriété de tous les objets d'une base de données. Bien que les tables, les vues, les déclencheurs et les séquences aient été quelque peu modifiés, l'approche ci-dessus a échoué pour les fonctions car la signature fait partie du nom de la fonction. Certes, j'ai une expérience MySQL et je ne connais pas très bien Postgres.

Cependant, pg_dump vous permet de vider uniquement le schéma et cela contient les instructions ALTER xxx OWNER TO yyy; dont vous avez besoin. Voici mon brin de magie Shell sur le sujet

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

est très simple

  1. su - postgres
  2. psql
  3. REASSIGN OWNED BY [ancien_utilisateur] À [nouveau_utilisateur];
  4. \ c [votre base de données]
  5. REASSIGN OWNED BY [ancien_utilisateur] À [nouveau_utilisateur];

terminé.

17
durenzo

très simple, essayez-le ...

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

J'aime celui-ci car il modifie les tables , les vues , séquences et fonctions propriétaires d'un certain schéma dans une fois (dans une instruction sql), sans créer de fonction et vous pouvez l'utiliser directement dans PgAdmin III et psql :

(Testé dans 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$$;

Basé sur les réponses fournies par @rkj, @AlannaRose, @SharoonThomas, @ user3560574 et cette réponse par @a_horse_with_no_name

Merci beaucoup.


Mieux encore: Changez également la base de données et le propriétaire du schéma .

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

Vous pouvez essayer ce qui suit dans 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
user3560574

Une telle commande n'existe pas dans PostgreSQL. Mais vous pouvez contourner ce problème en utilisant la méthode I décrite il y a quelque temps pour GRANT.

7
user80168

J'ai dû changer la propriété des tables, des vues et des séquences et j'ai trouvé que la bonne solution publiée par @rjk fonctionnait très bien, malgré un détail: si les noms des objets sont mixtes (par exemple, "Nom de la table"), cela échouera avec un " Erreur non trouvée.
Pour éviter cela, placez les noms d'objet avec '' 'comme ceci:

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

Des séquences

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;

Des vues

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;
5
Judge

Basé sur le answer by elysch , voici une solution pour plusieurs schémas:

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
$$;
3
JC Boggio

La réponse de @Alex Soto est la bonne et le Gist téléchargé par @Yoav Aner fonctionne également à condition qu'il n'y ait pas de caractères spéciaux dans les noms de table/vue (qui sont légaux dans postgres).

Vous devez leur échapper pour travailler et j'ai téléchargé un Gist pour cela: https://Gist.github.com/2911117

2
Sharoon Thomas

Le script Shell plus simple qui suit a fonctionné pour moi.

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

Où input $ 1 - nom d'utilisateur (base de données) $ 2 = schéma existant $ 3 = dans le nouveau schéma.

1
sramay

J'ai créé un script pratique pour cela; pg_change_db_owner.sh . Ce script modifie la propriété de toutes les tables, vues, séquences et fonctions d'un schéma de base de données, ainsi que le propriétaire du schéma lui-même.

Veuillez noter que si vous souhaitez simplement modifier la propriété de tous les objets, dans une base de données particulière, appartenant à un rôle de base de données particulier, vous pouvez simplement utiliser la commande REASSIGN OWNED à la place.

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

Puis redirigez le fichier de sauvegarde vers PostgreSQL en utilisant:

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

Comme il n'y a pas de propriétaire inclus, toute la table, le schéma, etc. créés sont créés sous l'utilisateur de connexion que vous spécifiez.

J'ai lu que cela pourrait être une bonne approche pour la migration entre les versions de PostgreSQL.

1
atwsKris

La solution acceptée ne prend pas en charge la propriété de la fonction suivante, la solution s’occupe de tout (lors de l’examen, j’ai remarqué qu’elle est similaire à @magiconair ci-dessus)

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
jsh

À partir de PostgreSQL 9.0, vous avez la possibilité de GRANT [priv name] ON ALL [object type] IN SCHEMA[priv name] est le type SELECT, INSERT, UPDATE, DELETE, etc et [object type] peut être l'un des suivants:

  • TABLES
  • SEQUENCES
  • FUNCTIONS

La documentation de PostgreSQL sur GRANT et REVOKE donne plus de détails à ce sujet. Dans certaines situations, il est toujours nécessaire d'utiliser des astuces impliquant les catalogues système (pg_catalog.pg_*) mais ce n'est pas aussi courant. Je fais souvent ce qui suit:

  1. BEGIN une transaction pour modifier les privs
  2. Changez la propriété de DATABASES en "rôle de DBA"
  3. Changez la propriété de SCHEMAS en "rôle de DBA"
  4. REVOKE ALL privs sur tous les TABLES, SEQUENCES et FUNCTIONS de tous les rôles
  5. GRANT SELECT, INSERT, UPDATE, DELETE sur les tables pertinentes/appropriées aux rôles appropriés
  6. COMMIT la transaction DCL.
1
Sean

Identique à l’approche de @ AlexSoto pour les fonctions:

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
1
Anton Smolkov

Docker: Modifiez le propriétaire de toutes les tables + séquences

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
0
Vojtech Vitek