Ответы:
REASSIGN OWNED
командуПримечание. Как упоминает @trygvis в ответе ниже , эта REASSIGN OWNED
команда доступна по крайней мере начиная с версии 8.2 и является гораздо более простым методом.
Поскольку вы меняете владельца для всех таблиц, вам, вероятно, также нужны представления и последовательности. Вот что я сделал:
Таблицы:
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
Последовательности:
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
Взгляды:
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
Вы, вероятно , можете немного высушить это, поскольку операторы alter идентичны для всех трех.
REASSIGN OWNED BY old_role [, ...] TO new_role
Вы можете использовать REASSIGN OWNED
команду.
REASSIGN OWNED BY old_role [, ...] TO new_role
Это изменяет все объекты, принадлежащие old_role
новой роли. Вам не нужно думать о том, какие объекты у пользователя, они все будут изменены. Обратите внимание, что это относится только к объектам внутри одной базы данных. Это не меняет владельца самой базы данных.
Доступно как минимум до 8.2. Их онлайн-документация только заходит так далеко.
ERROR: unexpected classid 3079
, Я думаю, что в настоящее время не работает, если есть какие-либо расширения.
Это: http://archives.postgresql.org/pgsql-bugs/2007-10/msg00234.php также является хорошим и быстрым решением и работает для нескольких схем в одной базе данных:
таблицы
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;
Материализованные представления
На основании этого ответа
SELECT 'ALTER TABLE '|| oid::regclass::text ||' OWNER TO my_new_owner;'
FROM pg_class WHERE relkind = 'm'
ORDER BY oid;
Это генерирует все необходимые операторы ALTER TABLE
/ ALTER SEQUENCE
/ ALTER VIEW
, копирует их и вставляет их обратно в plsql для их запуска.
Проверьте свою работу в psql, выполнив:
\dt *.*
\ds *.*
\dv *.*
Если вы хотите сделать это одним оператором sql, вам нужно определить функцию exec (), как указано в 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$;
Затем вы можете выполнить этот запрос, он изменит владельца таблиц, последовательностей и представлений:
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 - это новое имя postgresql для нового владельца.
В большинстве случаев вам нужно быть суперпользователем, чтобы выполнить это. Вы можете избежать этого, изменив владельца с вашего собственного пользователя на группу ролей, членом которой вы являетесь.
Спасибо RhodiumToad на #postgresql за помощь в этом.
Мне недавно пришлось сменить владельца всех объектов в базе данных. Хотя таблицы, представления, триггеры и последовательности были несколько легко изменены, вышеупомянутый подход не удался для функций, так как подпись является частью имени функции. Конечно, у меня есть опыт работы с MySQL, и я не очень знаком с Postgres.
Тем не менее, pg_dump позволяет вывести только схему, и она содержит ALTER xxx OWNER TO yyy; заявления вам нужны. Вот мой кусочек магии на тему
pg_dump -s YOUR_DB | grep -i 'owner to' | sed -e 's/OWNER TO .*;/OWNER TO NEW_OWNER;/i' | psqL YOUR_DB
grep
команду. Я сам новичок в Linux, но, насколько я понимаю, кажется, что sed
это нормально, особенно если вы в любом случае указываете регистр без учета регистра.
очень просто, попробуйте ...
select 'ALTER TABLE ' || table_name || ' OWNER TO myuser;' from information_schema.tables where table_schema = 'public';
очень просто
сделанный.
Мне нравится этот, так как он изменяет таблицы , представления , последовательности и функции- владельца определенной схемы за один раз (в одном выражении sql), не создавая функцию, и вы можете использовать ее непосредственно в PgAdmin III и psql :
(Проверено в 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$$;
На основании ответов, предоставленных @rkj, @AlannaRose, @SharoonThomas, @ user3560574 и этого ответа @a_horse_with_no_name
Большое спасибо.
Еще лучше: также измените владельца базы данных и схемы .
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
пусто, хотя SELECT c.* FROM pg_class c WHERE c.relkind = 'S';
перечисляет последовательности. Почему они могут не совпадать?
ALTER
запрос быть ALTER SEQUENCE
?
Мне пришлось изменить владельца таблиц, представлений и последовательностей, и я обнаружил, что отличное решение, опубликованное @rjk, работает нормально, несмотря на одну деталь: если имена объектов имеют смешанный регистр (например, «TableName»), это не удастся с « не найдена "- ошибка.
Чтобы обойти это, оберните имена объектов символом "" "следующим образом:
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;
Вы можете попробовать следующее в 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$$;
В PostgreSQL такой команды нет. Но вы можете обойти это, используя метод, который я описал некоторое время назад для GRANT.
Основываясь на ответе elysch , вот решение для нескольких схем:
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
$$;
Ответ @Alex Soto является правильным, и суть, загруженная @Yoav Aner, также работает при условии, что в именах таблиц / представлений нет специальных символов (которые допустимы в postgres).
Вам нужно избежать их на работу, и я загрузил суть для этого: 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 )
Затем передайте файл резервной копии обратно в PostgreSQL, используя:
psql -d database -U username -h hostname < filename
Поскольку владелец не включен, все созданные таблица, схема и т. Д. Создаются под указанным пользователем для входа.
Я читал, что это может быть хорошим подходом для миграции между версиями PostgreSQL.
Я создал удобный сценарий для этого; pg_change_db_owner.sh . Этот сценарий меняет владельца для всех таблиц, представлений, последовательностей и функций в схеме базы данных, а также для владельца самой схемы.
Обратите внимание, что если вы хотите просто изменить владельца всех объектов в конкретной базе данных, принадлежащих определенной роли базы данных, тогда вы можете просто использовать команду REASSIGN OWNED
вместо этого.
Начиная с PostgreSQL 9.0, у вас есть способность , GRANT [priv name] ON ALL [object type] IN SCHEMA
где [priv name]
является типичным SELECT, INSERT, UPDATE, DELETE, etc
и [object type]
может быть одним из:
TABLES
SEQUENCES
FUNCTIONS
Документы PostgreSQL GRANT
и REVOKE
более подробно об этом. В некоторых ситуациях все еще требуется использовать трюки с системными каталогами ( pg_catalog.pg_*
), но это не так часто. Я часто делаю следующее:
BEGIN
транзакция для изменения привилегийDATABASES
на "роль DBA"SCHEMAS
на "роль DBA"REVOKE ALL
privs на всех TABLES
, SEQUENCES
и FUNCTIONS
от всех ролейGRANT SELECT, INSERT, UPDATE, DELETE
на соответствующие / соответствующие таблицы для соответствующих ролейCOMMIT
транзакция DCL.Принятое решение не заботится о владении функциями. Следующее решение заботится обо всем (при рассмотрении я заметил, что оно похоже на @magiconair выше)
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};"
Следующий более простой сценарий оболочки работал для меня.
#!/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
Где ввод $ 1 - имя пользователя (база данных) $ 2 = существующая схема $ 3 = в новую схему.
То же, что и подход @ 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