Ubah PEMILIK pada semua tabel secara bersamaan di PostgreSQL

412

Bagaimana cara memodifikasi pemilik semua tabel di database PostgreSQL?

Saya mencoba ALTER TABLE * OWNER TO new_ownertetapi tidak mendukung sintaks asterisk.

Kai
sumber

Jawaban:

461

Lihat REASSIGN OWNEDperintah

Catatan: Seperti @trygvis menyebutkan jawaban di bawah ini , REASSIGN OWNEDperintah ini tersedia setidaknya sejak versi 8.2, dan merupakan metode yang jauh lebih mudah.


Karena Anda mengubah kepemilikan untuk semua tabel, kemungkinan Anda juga menginginkan tampilan dan urutan. Inilah yang saya lakukan:

Tabel:

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

Urutan:

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

Dilihat:

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

Anda mungkin bisa KERING sedikit karena statemen identik untuk ketiganya.


Alex Soto
sumber
10
+1 Terima kasih Alex. Saya telah membuat skrip bash kecil berdasarkan jawaban Anda, tersedia di gist.github.com/2482969
gingerlime
10
Lihat jawaban terbaru oleh @trygvis. Sejauh ini, jawaban paling sederhana:REASSIGN OWNED BY old_role [, ...] TO new_role
David
64
REASSIGN OWNED BY tidak berfungsi untuk objek yang dimiliki oleh postgres.
BrunoJCM
19
Juga, REASSIGN OWNED sebenarnya mempengaruhi kepemilikan semua database yang dimiliki oleh peran lama (Lihat: postgresql.org/docs/9.3/static/sql-reassign- owned.html ). Jadi, jika Anda hanya ingin mengubah kepemilikan satu basis data, waspadalah!
kitsune
3
Berdasarkan skrip @gingerlime, bspkrs (tidak dapat menemukan namanya) membuat skrip yang juga mengubah fungsi: https://gist.github.com/bspkrs/b997ed7f1eb1268f3403
elysch
538

Anda bisa menggunakan REASSIGN OWNEDperintah.

Ringkasan:

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

Ini mengubah semua objek yang dimiliki oleh old_roleperan baru. Anda tidak perlu memikirkan objek seperti apa yang dimiliki pengguna, semuanya akan diubah. Perhatikan bahwa itu hanya berlaku untuk objek di dalam satu basis data. Itu tidak mengubah pemilik database itu sendiri.

Ini tersedia kembali setidaknya 8.2. Dokumentasi online mereka hanya sejauh itu.

Coba Laugstøl
sumber
ERROR: unexpected classid 3079. Saya kira itu saat ini tidak berfungsi jika ada ekstensi.
Steve Jorgensen
40
Tampaknya ini tidak berfungsi untuk postgres pengguna, meskipun saya terhubung ke database yang saya buat (yaitu bukan database sistem), ia mengatakan ini: ERROR: tidak dapat menetapkan kembali kepemilikan objek yang dimiliki oleh postgres peran karena mereka diperlukan oleh database system
thnee
13
Seperti yang dilaporkan @thnee, REASSIGN memengaruhi semua objek dalam database dan itu tidak membedakan antara yang ditentukan pengguna dan objek sistem, jadi itu tidak berfungsi untuk postgres jika ada ekstensi yang memiliki tabel sendiri. Tetap saya lebih suka (+1) opsi ini untuk keanggunan, meskipun itu tidak banyak membantu saya (database saya sebelumnya dimiliki oleh postgres).
Pavel V.
6
Supaya jelas, perintah ini berfungsi di basis data bahwa Anda saat ini HANYA terhubung. Jika old_role memiliki objek di banyak basis data, Anda harus menyambungkan dan menjalankan perintah ini di masing-masing basis data itu
mavroprovato
11
ini sepertinya tidak berfungsi pada postgres yang dihosting melalui AWS RDS. Saya mendapatkan kesalahan ini "izin ditolak untuk menetapkan kembali objek" dan tautan ini menunjukkan mengapa: "Tampaknya satu-satunya cara untuk 'menetapkan kembali dimiliki' adalah sebagai superuser (yang bertentangan dengan dokumentasi), yang tidak dapat diakses dalam RDS. ' postgresql-archive.org/…
typoerrpr
198

Ini: http://archives.postgresql.org/pgsql-bugs/2007-10/msg00234.php juga merupakan solusi yang bagus dan cepat, dan berfungsi untuk banyak skema dalam satu basis data:

Tabel

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;

Urutan

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;

Tampilan

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;

Pandangan Terwujud

Berdasarkan jawaban ini

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

Ini menghasilkan semua ALTER TABLE/ ALTER SEQUENCE/ ALTER VIEWpernyataan yang diperlukan , salin dan tempel kembali ke plsql untuk menjalankannya.

Periksa pekerjaan Anda dalam psql dengan melakukan:

\dt *.*
\ds *.*
\dv *.*
rkj
sumber
Solusi bagus Satu-satunya masalah saya adalah saya telah mengekspor skrip dan kemudian mengeksekusi skrip yang diekspor. Saya SQL Server Guru tetapi saya tidak yakin apa cara pintas untuk mengeksekusi. Saya mengklik mengeksekusi kueri dan menjalankan pgScript. Apa yang saya lakukan salah?
Tyrone Moodley
1
Saya lebih suka ini karena berfungsi dari dalam plsql setelah login - skrip tingkat unix (jawaban favorit saat ini) memerlukan "-U postgres" dan entri kata sandi di lingkungan saya.
Bingung
2
Saya lebih suka jawaban ini karena (1) dapat dilakukan dalam psql atau pgAdmin (2) dengan mudah memungkinkan Anda untuk melihat objek yang akan Anda ubah. Saya juga menggunakan stackoverflow.com/questions/22803096/… , yang serupa, tetapi untuk fungsi.
AlannaRose
logika yang sangat bagus.
Emipro Technologies Pvt. Ltd.
42

Jika Anda ingin melakukannya dalam satu pernyataan sql, Anda perlu mendefinisikan fungsi exec () sebagaimana disebutkan dalam 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$;

Kemudian Anda dapat menjalankan kueri ini, itu akan mengubah pemilik tabel, urutan, dan tampilan:

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 adalah nama baru postgresql dari pemilik baru.

Dalam sebagian besar keadaan, Anda harus menjadi pengguna super untuk menjalankan ini. Anda dapat menghindari itu dengan mengubah pemilik dari pengguna Anda sendiri ke grup peran yang menjadi anggota Anda.

Terima kasih kepada RhodiumToad di #postgresql untuk membantu ini.

Johan Dahlin
sumber
2
Ini jauh lebih berguna karena mengubah kepemilikan seluruh skema, termasuk fungsi, indeks, urutan, dll. Terima kasih!
liviucmg
Itu tidak mengubah pemilik skema. Bagaimana cara mengubah pemilik skema juga?
Andrus
@Andrus ALTER DATABASE $ DB PEMILIK UNTUK $ PEMILIK;
Johan Dahlin
mengubah basis data mengubah seluruh pemilik basis data. Saya bertanya bagaimana cara mengubah pemilik skema.
Andrus
ALTER SCHEMA fred PEMILIK KE betty;
Eric Aldinger
21

Baru-baru ini saya harus mengubah kepemilikan semua objek dalam database. Meskipun tabel, tampilan, pemicu, dan urutan agak mudah diubah, pendekatan di atas gagal untuk fungsi karena tanda tangan adalah bagian dari nama fungsi. Memang, saya memiliki latar belakang MySQL dan saya tidak begitu mengenal Postgres.

Namun, pg_dump memungkinkan Anda untuk membuang skema saja dan ini berisi ALTER xxx OWNER TO yyy; pernyataan yang Anda butuhkan. Inilah sedikit sihir shell saya pada topik tersebut

pg_dump -s YOUR_DB | grep -i 'owner to' | sed -e 's/OWNER TO .*;/OWNER TO NEW_OWNER;/i' | psqL YOUR_DB
magiconair
sumber
Saya tidak yakin mengapa Anda menggunakan grepperintah. Saya sendiri baru mengenal Linux, tetapi dari pemahaman saya, sepertinya itu sedbaik-baik saja untuk digunakan, terutama karena Anda menentukan pertandingan yang case-insensitive.
Bobort
19

sangat sederhana, cobalah ...

 select 'ALTER TABLE ' || table_name || ' OWNER TO myuser;' from information_schema.tables where table_schema = 'public';
mwendamseke
sumber
4
Anda dapat menambahkan catatan bahwa string yang sesuai harus disalin dan dieksekusi. Bukannya tidak jelas: p
Nightscape
Yang termasuk menghapus semua kutipan di sekitar pernyataan pernyataan .. multi-kursor atau mengganti bantuan dalam kasus ini.
knownasilya
19

sangat sederhana

  1. su - postgres
  2. psql
  3. REASSIGN OWNED BY [old_user] TO [new_user];
  4. \ c [database Anda]
  5. REASSIGN OWNED BY [old_user] TO [new_user];

selesai

durenzo
sumber
1
Ini mungkin melakukan apa yang diinginkan sang querent. Sejauh ini yang paling mudah.
Geof Sawaya
1
Anda hanya terlambat 4 tahun ke pesta; gulir ke atas: stackoverflow.com/a/13535184/1772379
Ben Johnson
16

Saya suka yang ini karena memodifikasi tabel , tampilan , urutan dan fungsi pemilik skema tertentu dalam sekali jalan (dalam satu pernyataan sql), tanpa membuat fungsi dan Anda dapat menggunakannya langsung di PgAdmin III dan psql :

(Diuji dalam 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$$;

Berdasarkan jawaban yang diberikan oleh @rkj, @AlannaRose, @SharoonThomas, @ user3560574 dan jawaban ini oleh @a_horse_with_no_name

Terima kasih banyak.


Lebih baik lagi: Juga ganti pemilik basis data dan skema .

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$$;
elysch
sumber
LUAR BIASA! Mengapa postgres tidak menambahkan ini, saya tidak tahu!
pip
Dua pertanyaan: 1) Sepertinya baris "ALTER TABLE" pertama dan ketiga adalah dupes. Apakah itu disengaja (mis. Anda harus melakukan dua melewati tabel untuk mengubah kepemilikan?). 2) Kami menemukan bahwa information_schema.sequenceskosong meskipun SELECT c.* FROM pg_class c WHERE c.relkind = 'S';daftar urutan. Mengapa mereka tidak cocok?
GuyPaddock
Juga, bukankah seharusnya ALTERpermintaan kedua adalah ALTER SEQUENCE?
GuyPaddock
12

Saya harus mengubah kepemilikan tabel, tampilan, dan urutan dan menemukan solusi hebat yang diposting oleh @rjk berfungsi dengan baik - meskipun ada satu detail: Jika nama objek dari case campuran (mis. "TableName"), ini akan gagal dengan " tidak ditemukan "- teror.
Untuk menghindari ini, bungkus nama objek dengan '"' seperti ini:

Tabel

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;

Urutan

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;

Tampilan

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;
Hakim
sumber
10

Anda dapat mencoba yang berikut ini di 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$$;
pengguna3560574
sumber
6

Tidak ada perintah seperti itu di PostgreSQL. Tetapi Anda dapat mengatasinya menggunakan metode yang saya jelaskan beberapa waktu lalu untuk GRANT.


sumber
Terima kasih, artikel yang sangat bagus. Saya akan menyimpan ini sebagai referensi di masa depan. Menggunakan pgAdmin, saya akhirnya mencadangkan DB, menjatuhkan / menghapus DB, sementara memberikan new_owner hak yang diperlukan, dan kemudian kembali membuat dan mengembalikan DB sebagai new_owner, dengan opsi "tidak ada pemilik" diperiksa di jendela restore. Ini menghasilkan hasil yang saya cari dengan new_owner sebagai pemilik segalanya.
Kai
Postgres 9.3 memperkenalkan perintah REASSIGN OWNED. postgresql.org/docs/9.3/sql-reassign- owned.html
Georg Zimmer
3

Berdasarkan jawaban oleh elysch , berikut adalah solusi untuk beberapa skema:

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

Jawaban oleh @Alex Soto adalah jawaban yang benar dan inti yang diunggah oleh @Yoav Aner juga berfungsi asalkan tidak ada karakter khusus dalam tabel / nama tampilan (yang legal di postgres).

Anda perlu melarikan diri dari mereka untuk bekerja dan saya telah mengunggah inti untuk itu: https://gist.github.com/2911117

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

Kemudian pipa kembali file cadangan ke PostgreSQL menggunakan:

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

Karena tidak ada pemilik yang dimasukkan maka semua tabel, skema, dll, dibuat di bawah pengguna login yang Anda tentukan.

Saya telah membaca ini bisa menjadi pendekatan yang baik untuk migrasi antara versi PostgreSQL juga.

atwsKris
sumber
2

Saya telah membuat skrip yang mudah untuk itu; pg_change_db_owner.sh . Skrip ini mengubah kepemilikan untuk semua tabel, tampilan, urutan, dan fungsi dalam skema basis data dan juga pemilik skema itu sendiri.

Harap dicatat bahwa jika Anda hanya ingin mengubah kepemilikan semua objek, dalam database tertentu, yang dimiliki oleh peran database tertentu, maka Anda dapat menggunakan perintah REASSIGN OWNEDsaja.

Jakub Jirutka
sumber
1

Mulai dari PostgreSQL 9.0, Anda memiliki kemampuan ke GRANT [priv name] ON ALL [object type] IN SCHEMAmana [priv name]tipikal SELECT, INSERT, UPDATE, DELETE, etcdan [object type]dapat menjadi salah satu dari:

  • TABLES
  • SEQUENCES
  • FUNCTIONS

Dokumentasi PostgreSQL GRANTdan REVOKEmasuk ke detail lebih lanjut tentang ini. Dalam beberapa situasi masih diperlukan untuk menggunakan trik yang melibatkan katalog sistem ( pg_catalog.pg_*) tetapi itu tidak seperti biasa. Saya sering melakukan hal berikut:

  1. BEGIN transaksi untuk memodifikasi privs
  2. Ubah kepemilikan DATABASESmenjadi "peran DBA"
  3. Ubah kepemilikan SCHEMASmenjadi "peran DBA"
  4. REVOKE ALLprivs pada semua TABLES, SEQUENCESdan FUNCTIONSdari semua peran
  5. GRANT SELECT, INSERT, UPDATE, DELETE pada tabel yang relevan / sesuai untuk peran yang sesuai
  6. COMMIT transaksi DCL.
Sean
sumber
1

Solusi yang diterima tidak mengurus kepemilikan fungsi mengikuti solusi mengurus semuanya (saat meninjau saya perhatikan bahwa ini mirip dengan @magiconair di atas)

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};"
jsh
sumber
1

Script shell sederhana berikut ini bekerja untuk saya.

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

Di mana input $ 1 - nama pengguna (basis data) $ 2 = skema yang ada $ 3 = untuk skema baru.

sramay
sumber
1

Sama seperti pendekatan @ AlexSoto untuk fungsi:

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
Anton Smolkov
sumber
0

Docker: Ubah Pemilik semua Tabel + Urutan

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