Respostas:
REASSIGN OWNEDcomandoNota: 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.
REASSIGN OWNED BY old_role [, ...] TO new_role
Você pode usar o REASSIGN OWNEDcomando
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.
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 *.*
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.
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
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.
muito simples, experimente ...
select 'ALTER TABLE ' || table_name || ' OWNER TO myuser;' from information_schema.tables where table_schema = 'public';
é muito simples
feito.
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$$;
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?
ALTERconsulta não deveria ser uma ALTER SEQUENCE?
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:
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;
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$$;
Não existe esse comando no PostgreSQL. Mas você pode contornar isso usando o método que descrevi há algum tempo para GRANTs.
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
$$;
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
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.
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.
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:
TABLESSEQUENCESFUNCTIONSOs 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:
BEGIN uma transação para modificar os privsDATABASESpara uma "função DBA"SCHEMASpara a "função DBA"REVOKE ALLprivs em todos TABLES, SEQUENCESe FUNCTIONSde todas as funçõesGRANT SELECT, INSERT, UPDATE, DELETE em tabelas relevantes / apropriadas para as funções apropriadasCOMMIT a transação DCL.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};"
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.
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
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