Modifica PROPRIETARIO su tutte le tabelle contemporaneamente in PostgreSQL


412

Come posso modificare il proprietario di tutte le tabelle in un database PostgreSQL?

Ho provato ALTER TABLE * OWNER TO new_ownerma non supporta la sintassi dell'asterisco.

Risposte:


461

Vedi REASSIGN OWNEDcomando

Nota: come menziona @trygvis nella risposta di seguito , il REASSIGN OWNEDcomando è disponibile almeno dalla versione 8.2 ed è un metodo molto più semplice.


Dal momento che stai cambiando la proprietà di tutte le tabelle, probabilmente vorrai anche visualizzazioni e sequenze. Ecco cosa ho fatto:

tabelle:

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

sequenze:

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

Visualizzazioni:

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

Probabilmente potresti DRY un po 'perché le istruzioni alter sono identiche per tutti e tre.



10
+1 Grazie Alex. Ho creato un piccolo script bash basato sulla tua risposta, disponibile su gist.github.com/2482969
gingerlime

10
Vedi la recente risposta di @trygvis. La risposta più semplice è di gran lunga:REASSIGN OWNED BY old_role [, ...] TO new_role
David,

64
REASSIGN OWNED BY non funziona per gli oggetti di proprietà di Postgres.
BrunoJCM

19
Inoltre, REASSIGN OWNED influisce effettivamente sulla proprietà di tutti i database di proprietà del vecchio ruolo (Vedi: postgresql.org/docs/9.3/static/sql-reassign-owned.html ). Quindi, se vuoi solo cambiare la proprietà di un singolo database, fai attenzione!
kitsune,

3
Basato sullo script @gingerlime, bspkrs (non riusciva a trovare il suo nome) ne creò uno che cambia anche le funzioni: https://gist.github.com/bspkrs/b997ed7f1eb1268f3403
elysch

538

Puoi usare il REASSIGN OWNEDcomando

Sinossi:

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

Ciò modifica tutti gli oggetti di proprietà old_rolenel nuovo ruolo. Non devi pensare al tipo di oggetti che l'utente ha, saranno tutti cambiati. Si noti che si applica solo agli oggetti all'interno di un singolo database. Non altera neanche il proprietario del database stesso.

È disponibile per almeno 8.2. La loro documentazione online risale a molto tempo fa.


ERROR: unexpected classid 3079. Immagino che al momento non funziona se ci sono estensioni.
Steve Jorgensen,

40
Questo non sembra funzionare per gli utenti postgres, anche se sono connesso a un database che ho creato (cioè non un database di sistema), dice questo: ERRORE: impossibile riassegnare la proprietà degli oggetti di proprietà di postgres perché sono richiesti dal database sistema
thnee

13
Come riportato da @thnee, REASSIGN ha effetto su tutti gli oggetti nel database e non discrimina tra oggetti definiti dall'utente e oggetti di sistema, quindi non funziona per postgres se c'è un'estensione che ha le proprie tabelle. Preferisco comunque (+1) questa opzione per eleganza, anche se non mi ha aiutato molto (il mio database era precedentemente di proprietà di Postgres).
Pavel V.

6
Per essere chiari, questo comando funziona SOLO nel database a cui sei attualmente connesso. Se old_role possiede oggetti in più database, dovresti connetterti ed eseguire questo comando in ognuno di quei database
mavroprovato

11
questo non sembra funzionare su Postgres ospitato tramite AWS RDS. Ricevo questo errore "permesso negato di riassegnare gli oggetti" e questo link suggerisce perché: "Sembrerebbe che l'unico modo per" riassegnare la proprietà "sia un superutente (che è contraddetto dalla documentazione), che non è accessibile in RDS. " postgresql-archive.org/…
typoerrpr

198

Questo: http://archives.postgresql.org/pgsql-bugs/2007-10/msg00234.php è anche una soluzione piacevole e veloce e funziona per più schemi in un unico database:

tabelle

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;

sequenze

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;

Visualizzazioni

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;

Viste materializzate

Sulla base di questa risposta

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

Questo genera tutte le istruzioni ALTER TABLE/ ALTER SEQUENCE/ richieste ALTER VIEW, copiarle e incollarle nuovamente in plsql per eseguirle.

Controlla il tuo lavoro in psql facendo:

\dt *.*
\ds *.*
\dv *.*

Ottima soluzione Il mio unico problema era che avevo esportato gli script e quindi eseguito gli script esportati. Sono SQL Server Guru ma non sono sicuro di quale sia il collegamento da eseguire. Ho fatto clic su Esegui query ed esegui pgScript. Cosa stavo facendo di sbagliato?
Tyrone Moodley,

1
Ho preferito questo perché funziona da plsql una volta effettuato l'accesso - gli script di livello unix (attualmente la risposta preferita) richiedono un "-U postgres" e una password nel mio ambiente.
Stupito il

2
Preferisco questa risposta perché (1) può essere fatto in psql o pgAdmin (2) ti permette facilmente di vedere gli oggetti che modificherai. Ho anche usato stackoverflow.com/questions/22803096/… , che è simile, ma per le funzioni.
AlannaRose,


42

Se vuoi farlo in una istruzione sql, devi definire una funzione exec () come menzionato 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$;

Quindi puoi eseguire questa query, cambierà il proprietario di tabelle, sequenze e viste:

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 è il nuovo nome postgresql del nuovo proprietario.

Nella maggior parte dei casi è necessario essere superutente per eseguire questo. Puoi evitarlo cambiando il proprietario dal tuo utente in un gruppo di ruolo di cui sei membro.

Grazie a RhodiumToad su #postgresql per l'aiuto.


2
Questo è molto più utile poiché cambia la proprietà dell'intero schema, incluse funzioni, indici, sequenze, ecc. Grazie!
liviucmg,

Non cambia i proprietari dello schema. Come cambiare anche i proprietari dello schema?
Andrus,

@Andrus ALTER DATABASE $ DB PROPRIETARIO A $ PROPRIETARIO;
Johan Dahlin,

alter database modifica l'intero proprietario del database. Ho chiesto come cambiare i proprietari dello schema.
Andrus,

ALTER SCHEMA fred PROPRIETARIO A betty;
Eric Aldinger,

21

Di recente ho dovuto modificare la proprietà di tutti gli oggetti in un database. Sebbene le tabelle, le viste, i trigger e le sequenze siano state in qualche modo modificate facilmente, l'approccio di cui sopra non è riuscito per le funzioni poiché la firma fa parte del nome della funzione. Certo, ho un background MySQL e non ho molta familiarità con Postgres.

Tuttavia, pg_dump ti consente di scaricare solo lo schema e questo contiene ALTER xxx OWNER TO yyy; dichiarazioni che ti servono. Ecco il mio po 'di magia shell sull'argomento

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

Non sono sicuro del motivo per cui stai usando il grepcomando. Sono nuovo di Linux da solo, ma dalla mia comprensione, sembra che sedvada bene usare, soprattutto dal momento che stai specificando una corrispondenza senza distinzione tra maiuscole e minuscole.
Bobort,

19

molto semplice, provalo ...

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

4
È possibile aggiungere una nota che le stringhe corrispondenti devono essere copiate ed eseguite. Non che non sia ovvio: p
Nightscape

Il che include la rimozione di tutte le virgolette attorno alle istruzioni alter. In questo caso aiutano più cursori o sostituisci.
knownasilya,

19

è molto semplice

  1. su - postgres
  2. psql
  3. RASSEGNA OWNED DA [old_user] A [new_user];
  4. \ c [il tuo database]
  5. RASSEGNA OWNED DA [old_user] A [new_user];

fatto.


1
Questo probabilmente fa quello che voleva il richiedente. Di gran lunga il più semplice.
Geof Sawaya,

1
Sei in ritardo di soli 4 anni alla festa; scorrere verso l'alto: stackoverflow.com/a/13535184/1772379
Ben Johnson,

16

Mi piace questo dal momento che modifica tabelle , viste , sequenze e funzioni proprietarie di un determinato schema in una volta (in un'istruzione sql), senza creare una funzione e puoi usarla direttamente in PgAdmin III e psql :

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

Sulla base delle risposte fornite da @rkj, @AlannaRose, @SharoonThomas, @ user3560574 e questa risposta da @a_horse_with_no_name

Molte grazie.


Meglio ancora: cambia anche il proprietario del database e dello schema .

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

SORPRENDENTE! Perché Postgres non aggiunge questo non lo so!
pip

Due domande: 1) Sembra che la prima e la terza riga "ALTER TABLE" siano duplicate. È intenzionale (ad esempio devi fare due passaggi sui tavoli per cambiare proprietà?). 2) Stiamo scoprendo che information_schema.sequencesè vuoto anche se SELECT c.* FROM pg_class c WHERE c.relkind = 'S';elenca sequenze. Perché potrebbero non corrispondere?
GuyPaddock,

Inoltre, la seconda ALTERquery non dovrebbe essere una ALTER SEQUENCE?
GuyPaddock,

12

Ho dovuto cambiare la proprietà di tabelle, viste e sequenze e ho scoperto che la grande soluzione pubblicata da @rjk funziona bene, nonostante un dettaglio: se i nomi degli oggetti sono in maiuscolo (ad es. "TableName"), questo fallirà con un " non trovato "-error.
Per aggirare questo, avvolgere i nomi degli oggetti con '"' in questo modo:

tabelle

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;

sequenze

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;

Visualizzazioni

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

Puoi provare quanto segue 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$$;

6

Non esiste tale comando in PostgreSQL. Ma puoi aggirare il problema usando il metodo che ho descritto qualche tempo fa per GRANTs.


Grazie, bellissimo articolo. Lo terrò come riferimento futuro. Usando pgAdmin, ho terminato il backup del DB, l'eliminazione / eliminazione del DB, la concessione temporanea dei diritti necessari a new_owner e quindi la ricostruzione e il ripristino del DB come new_owner, con l'opzione "no owner" selezionata nella finestra di ripristino. Ciò ha prodotto i risultati che stavo cercando con new_owner come proprietario di tutto.
Kai,

Postgres 9.3 ha introdotto il comando REASSIGN OWNED. postgresql.org/docs/9.3/sql-reassign-owned.html
Georg Zimmer,

3

Sulla base della risposta di elysch , ecco una soluzione per più schemi:

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

La risposta di @Alex Soto è quella giusta e l'essenza caricata da @Yoav Aner funziona anche a condizione che non ci siano caratteri speciali nei nomi di tabella / vista (che sono legali in postgres).

Devi sfuggirli al lavoro e ho caricato una sintesi per questo: https://gist.github.com/2911117


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

Quindi reindirizzare il file di backup in PostgreSQL usando:

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

Poiché non è incluso alcun proprietario, tutta la tabella, lo schema, ecc. Creati vengono creati sotto l'utente di accesso specificato.

Ho letto che questo potrebbe essere un buon approccio per migrare anche tra le versioni PostgreSQL.


2

Ho creato uno script conveniente per quello; pg_change_db_owner.sh . Questo script modifica la proprietà di tutte le tabelle, viste, sequenze e funzioni in uno schema di database e anche il proprietario dello schema stesso.

Si noti che se si desidera semplicemente modificare la proprietà di tutti gli oggetti, in un determinato database, di proprietà di un determinato ruolo del database, è possibile utilizzare semplicemente il comando REASSIGN OWNED.


1

A partire da PostgreSQL 9.0, hai la possibilità di GRANT [priv name] ON ALL [object type] IN SCHEMAdove [priv name]è il tipico SELECT, INSERT, UPDATE, DELETE, etce [object type]può essere uno di:

  • TABLES
  • SEQUENCES
  • FUNCTIONS

I documenti di PostgreSQL proseguono GRANTe REVOKEapprofondiamo questo aspetto. In alcune situazioni è ancora necessario utilizzare trucchi che coinvolgono i cataloghi di sistema ( pg_catalog.pg_*) ma non è così comune. Faccio spesso quanto segue:

  1. BEGIN una transazione per modificare i priv
  2. Cambia la proprietà di DATABASESun "ruolo DBA"
  3. Cambia la proprietà del SCHEMAS"ruolo DBA"
  4. REVOKE ALLprivs su tutti TABLES, SEQUENCESe FUNCTIONSda tutti i ruoli
  5. GRANT SELECT, INSERT, UPDATE, DELETE su tabelle pertinenti / appropriate ai ruoli appropriati
  6. COMMIT la transazione DCL.

1

La soluzione accettata non si occupa della proprietà della funzione che segue la soluzione si occupa di tutto (durante la recensione ho notato che è simile a @magiconair sopra)

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

Il seguente script shell più semplice ha funzionato per 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

Dove input $ 1 - nome utente (database) $ 2 = schema esistente $ 3 = al nuovo schema.


1

Come l'approccio di @ AlexSoto per le funzioni:

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: modifica il proprietario di tutte le tabelle + sequenze

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.