Antworten:
REASSIGN OWNED
BefehlHinweis: Wie @trygvis in der folgenden Antwort erwähnt , ist der REASSIGN OWNED
Befehl seit mindestens Version 8.2 verfügbar und eine viel einfachere Methode.
Da Sie den Besitz für alle Tabellen ändern, möchten Sie wahrscheinlich auch Ansichten und Sequenzen. Folgendes habe ich getan:
Tabellen:
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
Sequenzen:
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
Ansichten:
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
Sie könnten das wahrscheinlich etwas austrocknen , da die alter-Anweisungen für alle drei identisch sind.
REASSIGN OWNED BY old_role [, ...] TO new_role
Sie können den REASSIGN OWNED
Befehl verwenden.
REASSIGN OWNED BY old_role [, ...] TO new_role
Dadurch werden alle Objekte, deren Eigentümer sie sind, old_role
in die neue Rolle geändert . Sie müssen nicht darüber nachdenken, welche Art von Objekten der Benutzer hat, sie werden alle geändert. Beachten Sie, dass dies nur für Objekte in einer einzelnen Datenbank gilt. Es ändert auch nicht den Eigentümer der Datenbank selbst.
Es ist ab mindestens 8.2 verfügbar. Ihre Online-Dokumentation reicht nur so weit zurück.
ERROR: unexpected classid 3079
. Ich denke, das funktioniert derzeit nicht, wenn es Erweiterungen gibt.
Dies: http://archives.postgresql.org/pgsql-bugs/2007-10/msg00234.php ist ebenfalls eine schöne und schnelle Lösung und funktioniert für mehrere Schemas in einer Datenbank:
Tabellen
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;
Sequenzen
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;
Ansichten
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;
Materialisierte Ansichten
Basierend auf dieser Antwort
SELECT 'ALTER TABLE '|| oid::regclass::text ||' OWNER TO my_new_owner;'
FROM pg_class WHERE relkind = 'm'
ORDER BY oid;
Dies erzeugt alle erforderlichen ALTER TABLE
/ ALTER SEQUENCE
/ ALTER VIEW
Anweisungen, kopieren Sie diese und fügen sie sie wieder in plsql zu laufen.
Überprüfen Sie Ihre Arbeit in psql, indem Sie Folgendes tun:
\dt *.*
\ds *.*
\dv *.*
Wenn Sie dies in einer SQL-Anweisung tun möchten, müssen Sie eine exec () - Funktion definieren, wie unter http://wiki.postgresql.org/wiki/Dynamic_DDL beschrieben
CREATE FUNCTION exec(text) returns text language plpgsql volatile
AS $f$
BEGIN
EXECUTE $1;
RETURN $1;
END;
$f$;
Anschließend können Sie diese Abfrage ausführen. Dadurch wird der Eigentümer von Tabellen, Sequenzen und Ansichten geändert:
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 ist der postgresql neue Name des neuen Besitzers.
In den meisten Fällen müssen Sie Superuser sein, um dies auszuführen. Sie können dies vermeiden, indem Sie den Eigentümer von Ihrem eigenen Benutzer in eine Rollengruppe ändern, in der Sie Mitglied sind.
Vielen Dank an RhodiumToad auf #postgresql für die Hilfe.
Ich musste kürzlich den Besitz aller Objekte in einer Datenbank ändern. Obwohl Tabellen, Ansichten, Trigger und Sequenzen leicht geändert werden konnten, schlug der obige Ansatz für Funktionen fehl, da die Signatur Teil des Funktionsnamens ist. Zugegeben, ich habe einen MySQL-Hintergrund und bin mit Postgres nicht so vertraut.
Mit pg_dump können Sie jedoch nur das Schema sichern, das ALTER xxx OWNER TO yyy enthält. Aussagen, die Sie brauchen. Hier ist mein bisschen Muschelmagie zum Thema
pg_dump -s YOUR_DB | grep -i 'owner to' | sed -e 's/OWNER TO .*;/OWNER TO NEW_OWNER;/i' | psqL YOUR_DB
grep
Befehl verwenden. Ich bin selbst neu in Linux, aber nach meinem Verständnis scheint sed
es in Ordnung zu sein , es zu verwenden, zumal Sie sowieso eine Übereinstimmung angeben, bei der die Groß- und Kleinschreibung nicht berücksichtigt wird.
sehr einfach, probieren Sie es aus ...
select 'ALTER TABLE ' || table_name || ' OWNER TO myuser;' from information_schema.tables where table_schema = 'public';
ist sehr einfach
erledigt.
Ich mag dieses, da es Tabellen , Ansichten , Sequenzen und Funktionen eines bestimmten Schemas auf einmal (in einer SQL-Anweisung) ändert, ohne eine Funktion zu erstellen, und Sie es direkt in PgAdmin III und psql verwenden können :
(Getestet 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$$;
Basierend auf den Antworten von @rkj, @AlannaRose, @SharoonThomas, @ user3560574 und dieser Antwort von @a_horse_with_no_name
Vielen Dank.
Noch besser: Ändern Sie auch den Datenbank- und Schemabesitzer .
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$$;
information_schema.sequences
leer ist, obwohl SELECT c.* FROM pg_class c WHERE c.relkind = 'S';
Sequenzen aufgelistet sind. Warum könnten sie nicht zusammenpassen?
ALTER
Abfrage nicht auch eine sein ALTER SEQUENCE
?
Ich musste den Besitz von Tabellen, Ansichten und Sequenzen ändern und fand, dass die großartige Lösung von @rjk einwandfrei funktioniert - trotz eines Details: Wenn die Objektnamen in Groß- und Kleinschreibung geschrieben sind (z. B. "Tabellenname"), schlägt dies mit einem "fehl. kein Fehler gefunden.
Um dies zu umgehen, schließen Sie die Objektnamen wie folgt mit '"' ein:
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;
In PostgreSQL 9 können Sie Folgendes versuchen
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$$;
In PostgreSQL gibt es keinen solchen Befehl. Aber man kann es umgehen Methode I beschrieben für GRANTs vor einiger Zeit.
Basierend auf der Antwort von elysch gibt es hier eine Lösung für mehrere Schemata:
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
$$;
Die Antwort von @Alex Soto ist die richtige und der von @Yoav Aner hochgeladene Kern funktioniert auch, vorausgesetzt, die Tabellen- / Ansichtsnamen enthalten keine Sonderzeichen (die in Postgres legal sind).
Sie müssen ihnen entkommen, um arbeiten zu können, und dafür habe ich eine Zusammenfassung hochgeladen: https://gist.github.com/2911117
pg_dump as insert statements
pg_dump -d -O database filename
-d ( data as inserts ) -O ( capital O is no owner )
Leiten Sie dann die Sicherungsdatei mit folgenden Elementen zurück an PostgreSQL:
psql -d database -U username -h hostname < filename
Da kein Eigentümer enthalten ist, werden alle erstellten Tabellen, Schemata usw. unter dem von Ihnen angegebenen Anmeldebenutzer erstellt.
Ich habe gelesen, dass dies auch ein guter Ansatz für die Migration zwischen PostgreSQL-Versionen sein könnte.
Ich habe dafür ein praktisches Skript erstellt. pg_change_db_owner.sh . Dieses Skript ändert den Besitz für alle Tabellen, Ansichten, Sequenzen und Funktionen in einem Datenbankschema sowie den Besitzer des Schemas.
Beachten Sie, dass Sie REASSIGN OWNED
stattdessen einfach den Befehl verwenden können, wenn Sie nur den Besitz aller Objekte in einer bestimmten Datenbank ändern möchten, die einer bestimmten Datenbankrolle gehört .
Ab PostgreSQL 9.0 haben Sie die Möglichkeit zu ermitteln, GRANT [priv name] ON ALL [object type] IN SCHEMA
wo dies [priv name]
typisch ist, SELECT, INSERT, UPDATE, DELETE, etc
und [object type]
können eine der folgenden sein:
TABLES
SEQUENCES
FUNCTIONS
PostgreSQLs Dokumente auf GRANT
und REVOKE
gehen Sie diesbezüglich näher darauf ein. In einigen Situationen müssen immer noch Tricks mit den Systemkatalogen ( pg_catalog.pg_*
) verwendet werden, aber dies ist bei weitem nicht so häufig. Ich mache häufig folgendes:
BEGIN
eine Transaktion zum Ändern der PrivilegienDATABASES
einer "DBA-Rolle"SCHEMAS
in die "DBA-Rolle"REVOKE ALL
privs auf alle TABLES
, SEQUENCES
und FUNCTIONS
aus allen RollenGRANT SELECT, INSERT, UPDATE, DELETE
auf relevanten / geeigneten Tabellen zu den entsprechenden RollenCOMMIT
die DCL-Transaktion.Die akzeptierte Lösung kümmert sich nicht um den Funktionsbesitz, nachdem die Lösung sich um alles gekümmert hat (bei der Überprüfung habe ich festgestellt, dass sie @magiconair oben ähnlich ist).
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};"
Das folgende einfachere Shell-Skript hat bei mir funktioniert.
#!/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
Wobei $ 1 eingegeben wird - Benutzername (Datenbank) $ 2 = vorhandenes Schema $ 3 = in neues Schema.
Entspricht dem Funktionsansatz von @ 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
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