Відповіді:
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
Ви могли б , ймовірно , СУХИЙ , що трохи , так як альтер заяви однакові для всіх трьох.
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 ВЛАСНИКА ДО 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 такої команди немає. Але ви можете працювати навколо нього з допомогою методу я описаний деякий час назад для грантів.
На основі відповіді від 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, також працює за умови, що в таблиці немає спеціальних символів (імена перегляду (які є законними на постграфах)).
Вам потрібно уникнути їх роботи, і я додав до цього суть: 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