PostgreSQL'de tüm tablolarda aynı anda SAHİBİ değiştirin


411

PostgreSQL veritabanındaki tüm tabloların sahibini nasıl değiştirebilirim?

Denedim ALTER TABLE * OWNER TO new_ownerama yıldız işaretini desteklemiyor.

Yanıtlar:


460

REASSIGN OWNEDKomuta bakın

Not: @trygvis'in aşağıdaki cevapta belirttiği gibi , REASSIGN OWNEDkomut en az 8.2 sürümünden beri mevcuttur ve çok daha kolay bir yöntemdir.


Tüm tabloların sahipliğini değiştirdiğiniz için, büyük olasılıkla görüntüleme ve sıralama da istersiniz. İşte yaptım:

Tablolar:

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

Diziler:

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

Görüntüleme:

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

Muhtemelen olabilir KURU alter ifadeleri üçü için de aynıdır çünkü biraz yukarı söyledi.



10
+1 Teşekkürler Alex. Cevabınıza dayanarak gist.github.com/2482969
gingerlime

10
@Trygvis tarafından verilen son cevaba bakınız. Şimdiye kadarki en basit cevap:REASSIGN OWNED BY old_role [, ...] TO new_role
David

64
REASSIGN OWNED BY postgres'e ait nesneler için çalışmaz.
BrunoJCM

19
Ayrıca, REASSIGN OWNED aslında eski rolün sahip olduğu tüm veritabanlarının sahipliğini etkiler (Bkz: postgresql.org/docs/9.3/static/sql-reassign-owned.html ). Yani sadece tek bir veritabanının sahipliğini değiştirmek istiyorsanız, dikkatli olun!
kitsune

3
@Gingerlime betiğine dayanarak, bspkrs (adını bulamadı) işlevleri de değiştiren bir tane oluşturdu: https://gist.github.com/bspkrs/b997ed7f1eb1268f3403
elysch

538

REASSIGN OWNEDKomutu kullanabilirsiniz .

Özet:

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

Bu, sahip olunan tüm nesneleri old_roleyeni role değiştirir. Kullanıcının ne tür nesnelere sahip olduğunu düşünmenize gerek yok, hepsi değişecek. Yalnızca tek bir veritabanındaki nesneler için geçerli olduğunu unutmayın. Veritabanının sahibini de değiştirmez.

En az 8.2'ye kadar kullanılabilir. Çevrimiçi belgeleri sadece bu kadar geriye gidiyor.


ERROR: unexpected classid 3079. Sanırım şu anda herhangi bir uzantı varsa işe yaramıyor.
Steve Jorgensen

40
Oluşturduğum bir veritabanına bağlı olduğum halde (yani bir sistem veritabanı değil) bu kullanıcı postgres için çalışmıyor gibi görünüyor, diyor ki: HATA: veritabanı tarafından gerekli olduğundan rol postgres sahip olunan nesnelerin sahipliğini yeniden atayamaz sistemi
thnee

13
@Thnee bildirdiği gibi, REASSIGN veritabanındaki tüm nesneleri etkiler ve kullanıcı tanımlı ve sistem nesneleri arasında ayrım yapmaz, bu nedenle kendi tabloları olan herhangi bir uzantı varsa postgres için çalışmaz. Yine de (+1) şıklık için bu seçeneği tercih ediyorum, bana çok yardımcı olmasa da (veritabanım daha önce postgres'e aitti).
Pavel

6
Açık olmak gerekirse, bu komut SADECE bağlı olduğunuz veritabanında çalışır. Old_role birden çok veritabanında nesneye sahipse, bu veritabanlarının her birine bu komutu bağlayıp çalıştırmalısınız
mavroprovato

11
Bu AWS RDS tarafından barındırılan postgres üzerinde çalışmıyor gibi görünüyor. Bu hatayı alıyorum "nesneleri yeniden atama izni reddedildi" ve bu bağlantı nedenini ortaya koyuyor: "Görünüşe göre" sahip olunan yeniden atamanın "tek yolunun (kullanıcı tarafından çelişen) bir süper kullanıcı olduğu anlaşılıyor RDS'de. ' postgresql-archive.org/…
typoerrpr

197

Bu: http://archives.postgresql.org/pgsql-bugs/2007-10/msg00234.php de güzel ve hızlı bir çözümdür ve tek bir veritabanında birden çok şema için çalışır:

Tablolar

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;

Diziler

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;

Görüntüleme

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;

Gerçekleştirilen Görünümler

Bu cevaba dayanarak

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

Bu gerekli tüm üretir ALTER TABLE / ALTER SEQUENCE/ ALTER VIEWifadelerini oluşturur, kopyalar ve çalıştırmak için plsql'e geri yapıştırır.

Psql'de çalışmanızı şunları yaparak kontrol edin:

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

Harika bir çözüm. Benim tek sorun ben komut dosyaları ihracat vardı ve daha sonra ihraç komut dosyaları yürütmek oldu. Ben SQL Server Guru değilim ama yürütmek için kısayol ne olduğundan emin değilim. Sorgu yürüt ve pgScript yürüt'ü tıkladım. Neyi yanlış yapıyordum?
Tyrone Moodley

1
Bir kez giriş plsql içinde çalıştığı için bunu tercih etti - unix seviyesi komut dosyaları (şu anda favori cevap) benim ortamda "-U postgres" ve şifre girişi gerektirir.
Dazed

2
Bu cevabı tercih ederim çünkü (1) psql veya pgAdmin (2) ile kolayca değiştirilebilecek nesneleri görmenizi sağlar. Ben de benzer, ancak işlevler için stackoverflow.com/questions/22803096/… kullandım .
AlannaRose

görkemli mantık.
Emipro Technologies Pvt. Ltd.

42

Bunu bir sql deyiminde yapmak istiyorsanız, aşağıda belirtildiği gibi bir exec () işlevi tanımlamanız gerekir http://wiki.postgresql.org/wiki/Dynamic_DDL'de

CREATE FUNCTION exec(text) returns text language plpgsql volatile
  AS $f$
    BEGIN
      EXECUTE $1;
      RETURN $1;
    END;
$f$;

Daha sonra bu sorguyu yürütebilirsiniz, tabloların, sıraların ve görünümlerin sahibini değiştirir:

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 yeni sahibinin postgresql yeni adıdır.

Çoğu durumda bunu gerçekleştirmek için süper kullanıcı olmanız gerekir. Sahibini kendi kullanıcınızdan üyesi olduğunuz bir rol grubuna değiştirerek bundan kaçınabilirsiniz.

#Postgresql'deki RhodiumToad'a bu konuda yardımcı olduğu için teşekkür ederiz.


2
Fonksiyonlar, dizinler, sekanslar vb. Dahil olmak üzere tüm şemanın sahipliğini değiştirdiği için bu çok daha kullanışlıdır.
liviucmg

Şema sahiplerini değiştirmez. Şema sahiplerini nasıl değiştirebilirim?
Andrus

@Andrus ALTER VERİTABANI $ DB SAHİBİNE SAHİBİNE;
Johan Dahlin

veritabanı değiştir tüm veritabanı sahibini değiştirir. Şema sahiplerinin nasıl değiştirileceğini sordum.
Andrus

ALTER SCHEMA SAHİBİNİ betty'e verdi;
Eric Aldinger

21

Son zamanlarda bir veritabanındaki tüm nesnelerin sahipliğini değiştirmek zorunda kaldım. Tablolar, görünümler, tetikleyiciler ve sekanslar biraz kolayca değiştirilse de, imza işlev adının bir parçası olduğu için işlevler için yukarıdaki yaklaşım başarısız oldu. Verilen bir MySQL arka plan var ve Postgres ile aşina değilim.

Ancak, pg_dump sadece şemayı boşaltmanıza izin verir ve bu da ytery ALTER xxx OWNER TO içerir ; İhtiyacınız olan ifadeler. İşte konu hakkında biraz büyü büyüsü

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

grepKomutu neden kullandığınızdan emin değilim . Linux'ta kendimi yeniyim, ancak anlayışımdan sed, özellikle de büyük / küçük harfe duyarlı olmayan bir eşleşme belirttiğiniz için, kullanımı iyi görünüyor .
Bobort

19

çok basit, dene ...

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

4
İlgili dizelerin kopyalanması ve yürütülmesi gerektiğini belirten bir not ekleyebilirsiniz. Belli değil: p
Gece manzarası

Hangi alter ifadeleri etrafında tüm tırnak kaldırma içerir .. çoklu imleçler veya değiştirme bu durumda yardımcı olur.
bilinenasilya

19

çok basit

  1. su - postgres
  2. psql'in
  3. REASSIGN [old_user] TARAFINDAN [new_user] SAHİBİ;
  4. \ c [veritabanınız]
  5. REASSIGN [old_user] TARAFINDAN [new_user] SAHİBİ;

yapılır.


1
Bu muhtemelen querent'in istediğini yapar. Şimdiye kadar en kolay.
Geof Sawaya

1
Partiye sadece 4 yıl geç kaldınız; yukarı kaydırma: stackoverflow.com/a/13535184/1772379
Ben Johnson

16

Değiştirdiği beri bu gibi ben tablolar , görünümler , dizileri ve işlevleri belli sahibi şema içinde tek seferde bir işlevi oluşturma ve doğrudan bilgisayara kullanabilirsiniz olmadan, (bir SQL deyiminde) pgAdmin III ve psql'in :

(PostgreSql v9.2'de test edilmiştir)

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

@Rkj, @AlannaRose, @SharoonThomas, @ user3560574 tarafından sağlanan yanıtlara dayanarak ve bu cevap @a_horse_with_no_name tarafından

Çok teşekkürler.


Daha da iyisi: Veritabanı ve şema sahibini de değiştirin .

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

İNANILMAZ! Neden postgres bunu eklemiyor bilmiyorum!
pip

İki soru: 1) Birinci ve üçüncü "ALTER TABLE" satırları dupes gibi görünüyor. Bu kasıtlı mı (örneğin, sahipliği değiştirmek için masaların üzerinden iki geçiş yapmak zorunda mısınız?). 2) Dizileri listelemesine information_schema.sequencesrağmen boş olduğunu SELECT c.* FROM pg_class c WHERE c.relkind = 'S';görüyoruz. Neden uyuşmayabilirler?
GuyPaddock

Ayrıca, ikinci ALTERsorgu bir değil ALTER SEQUENCEmi?
GuyPaddock

12

Tablolar, görünümler ve dizilerin sahipliğini değiştirmek zorunda kaldı ve @rjk tarafından yayınlanan büyük bir çözüm iyi çalışıyor bulundu - bir ayrıntıya rağmen: Nesne adları karışık durumda (örneğin "TableName"), bu bir " Hata bulunamadı.
Bunu atlamak için, nesne adlarını şu şekilde "" ile sarın:

Tablolar

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;

Diziler

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;

Görüntüleme

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

PostgreSQL 9'da aşağıdakileri deneyebilirsiniz

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

PostgreSQL'de böyle bir komut yoktur. Ancak GRANT'lar için bir süre önce tarif ettiğim yöntemi kullanarak bu sorunu çözebilirsiniz.


Teşekkür ederim, çok güzel bir makale. Bunu ileride referans olarak tutacağım. PgAdmin kullanarak, DB'yi yedekledim, DB'yi bıraktım / sildim, geçici olarak new_owner'a gerekli hakları verdim ve sonra geri yükleme penceresinde "sahip yok" seçeneği işaretlendiğinde DB'yi new_owner olarak yeniden oluşturup geri yükledim. Bu, her şeyin sahibi olarak new_owner ile aradığım sonuçları üretti.
Kai

Postgres 9.3 REASSIGN OWNED komutunu tanıttı. postgresql.org/docs/9.3/sql-reassign-owned.html
Georg Zimmer

3

Elysch'in cevabına dayanarak, birden fazla şema için bir çözüm:

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

@Alex Soto'nun yanıtı doğru ve @Yoav Aner tarafından yüklenen özü, tablo / görünüm adlarında (postgres için yasal olan) özel karakterler olmaması koşuluyla da çalışıyor.

Çalışmak için onlardan kaçmanız gerekiyor ve bunun için bir özgeçmiş yükledim: 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 )

Sonra yedekleme dosyasını PostgreSQL'e geri gönderin:

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

Sahip bulunmadığından, oluşturulan tüm tablo, şema vb. Belirttiğiniz oturum açma kullanıcısı altında oluşturulur.

Bu PostgreSQL sürümleri arasında geçiş için iyi bir yaklaşım olabilir okudum.


2

Bunun için uygun bir senaryo oluşturdum; pg_change_db_owner.sh . Bu komut dosyası, bir veritabanı şemasındaki tüm tabloların, görünümlerin, sıraların ve işlevlerin ve aynı zamanda şemanın sahibinin sahipliğini değiştirir.

Belirli bir veritabanındaki belirli bir veritabanı rolüne ait olan tüm nesnelerin sahipliğini değiştirmek istiyorsanız, REASSIGN OWNEDbunun yerine komutu kullanabilirsiniz .


1

PostgreSQL 9.0 itibaren, yeteneğine sahip GRANT [priv name] ON ALL [object type] IN SCHEMAyerlerde [priv name]tipik SELECT, INSERT, UPDATE, DELETE, etcve [object type]biri olabilir:

  • TABLES
  • SEQUENCES
  • FUNCTIONS

PostgreSQL'in dokümanları üzerinde durun GRANTve bununla ilgili REVOKEdaha ayrıntılı bilgi edinin. Bazı durumlarda hala sistem katalogları ( pg_catalog.pg_*) ile ilgili hileler kullanmak gerekir, ancak neredeyse o kadar yaygın değildir. Sık sık aşağıdakileri yaparım:

  1. BEGIN gizlilikleri değiştirmek için bir işlem
  2. Sahipliğini DATABASES"DBA rolü" olarak değiştirme
  3. Sahipliğini SCHEMAS"DBA rolü" olarak değiştir
  4. REVOKE ALLtümü üzerinde privs TABLES, SEQUENCESve FUNCTIONStüm rollerden
  5. GRANT SELECT, INSERT, UPDATE, DELETE ilgili / uygun tablolarda uygun rollere
  6. COMMIT DCL işlemi.

1

Kabul edilen çözüm, çözümün ardından her şeyle ilgilenen işlev sahipliğine dikkat etmez (gözden geçirirken yukarıdaki @magiconair ile benzer olduğunu fark ettim)

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

Aşağıdaki basit kabuk betiği benim için çalıştı.

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

Burada $ 1 girişi - kullanıcı adı (veritabanı) $ 2 = mevcut şema $ 3 = yeni şemaya.


1

@ AlexSoto'nun işlevler yaklaşımı ile aynı:

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: Tüm Tabloların ve Dizilerin Sahibini Değiştir

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.