Modifique OWNER em todas as tabelas simultaneamente no PostgreSQL


412

Como modifico o proprietário de todas as tabelas em um banco de dados PostgreSQL?

Eu tentei, ALTER TABLE * OWNER TO new_ownermas ele não suporta a sintaxe do asterisco.

Respostas:


461

Ver REASSIGN OWNEDcomando

Nota: Como @trygvis menciona na resposta abaixo , o REASSIGN OWNEDcomando está disponível desde pelo menos a versão 8.2 e é um método muito mais fácil.


Como você está alterando a propriedade de todas as tabelas, provavelmente também deseja visualizações e sequências. Aqui está o que eu fiz:

Tabelas:

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

Sequências:

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

Visualizações:

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

Você provavelmente poderia secar um pouco, pois as instruções alter são idênticas para os três.



10
+1 Obrigado Alex. Eu criei um pequeno script bash com base em sua resposta, disponível em gist.github.com/2482969
— gingerlime

10
Veja a resposta recente de @trygvis. Resposta mais simples, de longe:REASSIGN OWNED BY old_role [, ...] TO new_role
— David

64
A nova atribuição de propriedade de não funciona para objetos pertencentes ao postgres.
— BrunoJCM

19
Além disso, REASSIGN OWNED realmente afeta a propriedade de todos os bancos de dados pertencentes à função antiga (consulte: postgresql.org/docs/9.3/static/sql-reassign-owned.html ). Portanto, se você deseja alterar apenas a propriedade de um único banco de dados, tenha cuidado!
— kitsune

3
Baseado em @gingerlime roteiro, bspkrs (não poderia encontrar o seu nome) criou um que também altera as funções: https://gist.github.com/bspkrs/b997ed7f1eb1268f3403
— elysch

538

Você pode usar o REASSIGN OWNEDcomando

Sinopse:

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

Isso altera todos os objetos pertencentes a old_rolepara a nova função. Você não precisa pensar em que tipo de objetos o usuário possui, todos eles serão alterados. Observe que isso se aplica apenas a objetos dentro de um único banco de dados. Também não altera o proprietário do próprio banco de dados.

Está disponível de volta a pelo menos 8.2. Sua documentação on-line remonta apenas a esse ponto.


ERROR: unexpected classid 3079. Acho que atualmente não funciona se houver extensões.
— Steve Jorgensen

40
Isso parece não funcionar para os usuários do postgres, mesmo estando conectado a um banco de dados que criei (isto é, não um banco de dados do sistema), ele diz o seguinte: ERRO: não é possível reatribuir a propriedade dos objetos pertencentes aos papéis do postgres porque eles são solicitados pelo banco de dados sistema
— thnee 8/03/2019

13
Como o @thnee relatou, o REASSIGN afeta todos os objetos no banco de dados e não discrimina entre objetos definidos pelo usuário e objetos do sistema, portanto, não funciona para o postgres se houver alguma extensão com suas próprias tabelas. Ainda prefiro (+1) esta opção por elegância, mesmo que não tenha me ajudado muito (meu banco de dados era de propriedade do postgres).
— Pavel V.

6
Só para esclarecer, este comando funciona no banco de dados que você está conectado SOMENTE no momento. Se o OLD_ROLE possui objetos em vários bancos de dados, você deve conectar e executar este comando em cada um desses bancos de dados
— mavroprovato

11
isso parece não funcionar no postgres hospedado pelo AWS RDS. Estou recebendo esse erro "permissão negada para reatribuir objetos" e este link sugere o motivo: "Parece que a única maneira de 'reatribuir propriedade' é como um superusuário (que é contradito pela documentação), que não está acessível no RDS. postgresql-archive.org/…
— typoerrpr

198

Esta: http://archives.postgresql.org/pgsql-bugs/2007-10/msg00234.php também é uma solução agradável e rápida e funciona para vários esquemas em um banco de dados:

Tabelas

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;

Sequências

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;

Visualizações

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;

Visualizações materializadas

Com base nesta resposta

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

Isso gera todas as instruções / ALTER TABLE/ necessárias , copie-as e cole-as novamente no plsql para executá-las.ALTER SEQUENCEALTER VIEW

Verifique seu trabalho no psql fazendo:

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

Ótima solução. Meu único problema foi que eu exportei os scripts e depois executei os scripts exportados. Eu sou o SQL Server Guru, mas não sei ao certo qual é o atalho a ser executado. Cliquei em executar consulta e executar pgScript. O que eu estava fazendo de errado?
— Tyrone Moodley

1
Eu preferi isso, pois ele trabalha no plsql uma vez logado - os scripts no nível unix (atualmente a resposta favorita) exigem um "-U postgres" e uma entrada de senha no meu ambiente.
— Apraz

2
Prefiro esta resposta porque (1) ela pode ser feita no psql ou no pgAdmin (2), e permite ver facilmente os objetos que você estará alterando. Eu também usei stackoverflow.com/questions/22803096/… , que é semelhante, mas para funções.
— AlannaRose

lógica esplêndida.
— Emipro Technologies Unip. Ltd.

42

Se você quiser fazer isso em uma instrução sql, precisará definir uma função exec () conforme mencionado em 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$;

Então você pode executar esta consulta, ela mudará o proprietário de tabelas, sequências e visualizações:

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 é o novo nome do novo proprietário do postgresql.

Na maioria das circunstâncias, você precisa ser superusuário para executar isso. Você pode evitar que, alterando o proprietário de seu próprio usuário para um grupo de funções do qual você seja membro.

Agradecemos ao RhodiumToad no #postgresql por ajudar com isso.


2
Isso é muito mais útil, pois altera a propriedade de todo o esquema, incluindo funções, índices, sequências, etc. Obrigado!
— liviucmg

Não altera os proprietários do esquema. Como alterar os proprietários do esquema também?
— Andrus

@Andrus ALTER O PROPRIETÁRIO DE $ DB A $ OWNER;
— Johan Dahlin

alterar banco de dados altera o proprietário inteiro do banco de dados. Perguntei como alterar os proprietários do esquema.
— 18720 Andrus

ALTER SCHEMA FRED PROPRIETÁRIO A Betty;
— precisa saber é o seguinte

21

Recentemente, tive que alterar a propriedade de todos os objetos em um banco de dados. Embora tabelas, visualizações, gatilhos e seqüências tenham sido alterados com alguma facilidade, a abordagem acima falhou para as funções, pois a assinatura faz parte do nome da função. Concedido, eu tenho um histórico no MySQL e não estou familiarizado com o Postgres.

No entanto, pg_dump permite despejar apenas o esquema e isso contém o ALTER xxx OWNER TO yyy; declarações que você precisa. Aqui está o meu pouco de magia shell sobre o tema

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

Não sei por que você está usando o grepcomando Eu sou novo no Linux, mas, pelo que entendi, parece que sedé muito bom de usar, especialmente porque você está especificando uma correspondência que não diferencia maiúsculas de minúsculas.
— Bobort 9/03

19

muito simples, experimente ...

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

4
Você pode adicionar uma nota de que as seqüências correspondentes devem ser copiadas e executadas. Não que não é óbvio: p
— Nightscape

O que inclui a remoção de todas as aspas ao redor das instruções alter.
— knownasilya

19

é muito simples

  1. su - postgres
  2. psql
  3. REASSINAR PROPRIEDADE POR [old_user] TO [new_user];
  4. \ c [seu banco de dados]
  5. REASSINAR PROPRIEDADE POR [old_user] TO [new_user];

feito.


1
Isso provavelmente faz o que o consultor queria. De longe o mais fácil.
— Geof Sawaya

1
Você está com apenas 4 anos de atraso na festa; Role para cima: stackoverflow.com/a/13535184/1772379
— Ben Johnson

16

Eu gosto deste, pois modifica tabelas , visualizações , sequências e funções proprietárias de um determinado esquema de uma só vez (em uma instrução sql), sem criar uma função e você pode usá-lo diretamente no PgAdmin III e no psql :

(Testado no 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$$;

Com base nas respostas fornecidas por @rkj, @AlannaRose, @SharoonThomas, @ user3560574 e esta resposta por @a_horse_with_no_name

Muito obrigado.


Melhor ainda: altere também o proprietário do banco de dados e do esquema .

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

SURPREENDENTE! Por que o postgres não adiciona isso, eu não sei!
— pip

Duas perguntas: 1) Parece que a primeira e a terceira linhas "ALTER TABLE" são burras. Isso é intencional (por exemplo, você precisa fazer duas passagens sobre as tabelas para mudar de propriedade?). 2) Descobrimos que ele information_schema.sequencesestá vazio, apesar de SELECT c.* FROM pg_class c WHERE c.relkind = 'S';listar sequências. Por que eles não combinam?
— precisa saber é o seguinte

Além disso, a segunda ALTERconsulta não deveria ser uma ALTER SEQUENCE?
— GuyPaddock

12

Eu tive que mudar a propriedade das tabelas, visualizações e seqüências e achei que a ótima solução postada por @rjk está funcionando bem - apesar de um detalhe: se os nomes dos objetos forem de letras maiúsculas e minúsculas (por exemplo, "TableName"), isso falhará com " erro não encontrado.
Para contornar isso, envolva os nomes dos objetos com '"' assim:

Tabelas

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;

Sequências

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;

Visualizações

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

Você pode tentar o seguinte no 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

Não existe esse comando no PostgreSQL. Mas você pode contornar isso usando o método que descrevi há algum tempo para GRANTs.


Obrigado, artigo muito bom. Vou manter isso como uma referência futura. Usando o pgAdmin, acabei fazendo backup do banco de dados, removendo / excluindo o banco de dados, concedendo temporariamente a new_owner os direitos necessários e, em seguida, recriando e restaurando o DB como new_owner, com a opção "no owner" marcada na janela de restauração. Isso produziu os resultados que eu estava procurando com new_owner como o proprietário de tudo.
— Kai

O Postgres 9.3 introduziu o comando REASSIGN OWNED. postgresql.org/docs/9.3/sql-reassign-owned.html
— Georg Zimmer

3

Com base na resposta de elysch , aqui está uma solução para vários esquemas:

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

A resposta de @Alex Soto é a correta e a essência enviada por @Yoav Aner também funciona, desde que não haja caracteres especiais nos nomes de tabela / exibição (que são legais no postgres).

Você precisa evitá-los para o trabalho e eu carreguei uma essência para isso: 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 )

Em seguida, envie o arquivo de backup novamente para o PostgreSQL usando:

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

Como não há proprietário incluído, todas as tabelas, esquemas etc. criados são criados no usuário de login especificado.

Eu li que isso poderia ser uma boa abordagem para a migração entre as versões do PostgreSQL também.


2

Eu criei um script conveniente para isso; pg_change_db_owner.sh . Esse script altera a propriedade de todas as tabelas, visualizações, sequências e funções em um esquema de banco de dados e também o proprietário do próprio esquema.

Observe que, se você quiser apenas alterar a propriedade de todos os objetos, em um banco de dados específico, pertencentes a uma função de banco de dados específica, basta usar o comando REASSIGN OWNED.


1

A partir do PostgreSQL 9.0, você tem a capacidade de GRANT [priv name] ON ALL [object type] IN SCHEMAonde [priv name]está o típico SELECT, INSERT, UPDATE, DELETE, etce [object type]pode ser um dos seguintes:

  • TABLES
  • SEQUENCES
  • FUNCTIONS

Os documentos do PostgreSQL estão disponíveis GRANTe REVOKEentram em mais detalhes sobre isso. Em algumas situações, ainda é necessário usar truques envolvendo os catálogos do sistema ( pg_catalog.pg_*), mas isso não é tão comum. Eu frequentemente faço o seguinte:

  1. BEGIN uma transação para modificar os privs
  2. Alterar a propriedade de DATABASESpara uma "função DBA"
  3. Alterar a propriedade de SCHEMASpara a "função DBA"
  4. REVOKE ALLprivs em todos TABLES, SEQUENCESe FUNCTIONSde todas as funções
  5. GRANT SELECT, INSERT, UPDATE, DELETE em tabelas relevantes / apropriadas para as funções apropriadas
  6. COMMIT a transação DCL.

1

A solução aceita não cuida da propriedade da função. A seguinte solução cuida de tudo (ao revisar, observei que é semelhante ao @magiconair acima)

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

O seguinte script shell mais simples funcionou para mim.

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

Onde entrada $ 1 - nome de usuário (banco de dados) $ 2 = esquema existente $ 3 = para o novo esquema.


1

Igual à abordagem de @ AlexSoto para funções:

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: modificar proprietário de todas as tabelas + seqüências

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.