Змініть ВЛАСНИКА на всіх таблицях одночасно в PostgreSQL


409

Як змінити власника всіх таблиць у базі даних PostgreSQL?

Я спробував, ALTER TABLE * OWNER TO new_ownerале він не підтримує синтаксис зірочок.

Відповіді:


459

Дивіться 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

Ви могли б , ймовірно , СУХИЙ , що трохи , так як альтер заяви однакові для всіх трьох.



10
+1 Дякую Алекс. На основі вашої відповіді я створив невеликий сценарій bash, доступний на сайті gist.github.com/2482969
gingerlime

10
Дивіться останню відповідь від @trygvis. Найпростіша відповідь на сьогодні:REASSIGN OWNED BY old_role [, ...] TO new_role
Девід

64
REASSIGN Owned BY не працює для об’єктів, що належать postgres.
BrunoJCM

19
Крім того, REASSIGN OWNED фактично впливає на право власності на всі бази даних, що належать старій ролі (Див.: Postgresql.org/docs/9.3/static/sql-reassign-owned.html ). Тож якщо ви хочете лише змінити право власності на єдину базу даних, будьте уважні!
kitsune

3
На основі сценарію @gingerlime, bspkrs (не вдалося знайти його ім'я) створив такий, який також змінює функції: https://gist.github.com/bspkrs/b997ed7f1eb1268f3403
elysch

537

Ви можете використовувати REASSIGN OWNEDкоманду.

Конспект:

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

Це змінює всі об'єкти, якими належить old_roleнова роль. Не потрібно думати про те, які об’єкти у користувача є, всі вони будуть змінені. Зауважте, що це стосується лише об'єктів всередині однієї бази даних. Це також не змінює власника бази даних.

Він доступний як мінімум до 8.2. Їх онлайн-документація йде лише так далеко.


ERROR: unexpected classid 3079. Я думаю, що зараз не працює, якщо є розширення.
Стів Йоргенсен

40
Здається, це не працює для користувальницьких postgres, навіть якщо я підключений до створеної мною бази даних (тобто не системної бази даних), це говорить так: ПОМИЛКА: не можна перепризначити право власності на об'єкти, що належать рольовим постграфам, оскільки їх вимагає база даних система
thnee

13
Як повідомляв @thnee, REASSIGN впливає на всі об'єкти в базі даних, і він не розрізняє визначені користувачем і системні об'єкти, тому він не працює для постгресів, якщо у будь-якого розширення є власні таблиці. І все-таки я віддаю перевагу (+1) цей варіант для елегантності, навіть якщо він мені не дуже допомагав (моя база даних раніше була власністю postgres).
Павло В.

6
Щоб зрозуміти, ця команда працює в базі даних, з якою ви зараз підключені ТІЛЬКО. Якщо old_role володіє об'єктами в декількох базах даних, вам слід підключити та запустити цю команду в кожній із цих баз даних
mavroprovato

11
це, мабуть, не працює на postgres, розміщеному через AWS RDS. Я отримую цю помилку "дозвіл відмовлено перепризначати об'єкти", і це посилання підказує чому: "Здається, єдиний спосіб" перепризначити право власності "- це супер-користувач (що суперечить документації), який недоступний в RDS. ' postgresql-archive.org/…
typoerrpr

196

Це: 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 Server, але я не впевнений, що це ярлик для виконання. Я натиснув виконати запит та виконати pgScript. Що я робив не так?
Тайрон Мудлі

1
Я віддав перевагу цьому, оскільки це працює зсередини plsql після входу в систему - сценарії unix рівня (на даний момент улюблена відповідь) вимагають "-U postgres" та введення пароля в моєму середовищі.
Приглушене

2
Я віддаю перевагу цій відповіді, оскільки (1) це можна зробити в psql або pgAdmin (2), він дозволяє легко бачити об'єкти, які ви будете змінювати. Я також використовував stackoverflow.com/questions/22803096/… , що схоже, але для функцій.
AlannaRose

чудова логіка.
Emipro Technologies Pvt. ТОВ

42

Якщо ви хочете зробити це в одному операторі 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 за допомогу в цьому.


2
Це набагато корисніше, оскільки воно змінює право власності на всю схему, включаючи функції, індекси, послідовності тощо. Дякую!
liviucmg

Це не змінює власників схеми. Як змінити власників схеми також?
Андрус

@Andrus АЛЬТЕРБУВАННЯ $ ВЛАСНИКА ДО $ ВЛАСНИКА;
Йохан Далін

змінити базу даних зміни цілого власника бази даних. Я запитав, як змінити власників схеми.
Андрус

АЛЕШЕ СХЕМА ФРЕДА ВЛАСНИКА БЕТТІ;
Ерік Олдінгер

21

Нещодавно мені довелося змінити право власності на всі об’єкти в базі даних. Хоча таблиці, представлення, тригери та послідовності були дещо легко змінені, вищезгаданий підхід не вдався до функцій, оскільки підпис є частиною назви функції. Зрозуміло, у мене є 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це просто чудово використовувати, тим більше що ви все одно вказуєте на збіг, що не враховує регістр.
Бобборт

19

дуже просто, спробуйте ...

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

4
Ви можете додати зауваження, що відповідні рядки потрібно скопіювати та виконати. Не те, що це не очевидно: p
Nightscape

Що включає вилучення всіх лапок навколо заяв про alter .. багато курсорів або заміни допомагає в цьому випадку.
knownasilya

19

дуже просто

  1. су - постгреси
  2. psql
  3. ПОВЕРНЕННЯ, ВЛАСНЕНО [old_user] TO [new_user];
  4. \ c [ваша база даних]
  5. ПОВЕРНЕННЯ, ВЛАСНЕНО [old_user] TO [new_user];

зроблено.


1
Це, мабуть, робить те, що хотів querent. На сьогоднішній день найпростіше.
Геоф Савейя

1
Ви спізнилися лише на 4 роки; прокрутити вгору: stackoverflow.com/a/13535184/1772379
Бен Джонсон

16

Мені це подобається, оскільки він змінює таблиці , представлення , послідовності та функції власника певної схеми за один раз (в одному операторі 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$$;

ДИВОВИЖНИЙ! Чому postgres не додає цього, я не знаю!
піп

Два запитання: 1) Схоже, що перша та третя лінії "ВІДПРАВЛІТЬ ТАБЛИЦЯ" - це дуп. Це навмисно (наприклад, чи потрібно робити два проходи над таблицями, щоб змінити право власності?). 2) Ми виявляємо, що information_schema.sequencesце порожньо, хоча SELECT c.* FROM pg_class c WHERE c.relkind = 'S';перелічені послідовності. Чому вони можуть не відповідати?
GuyPaddock

Крім того, чи не повинен бути другий ALTERзапит ALTER SEQUENCE?
GuyPaddock

12

Мені довелося змінити право власності на таблиці, перегляди та послідовності, і я знайшов чудове рішення, розміщене @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;

10

Ви можете спробувати наступне в 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

У PostgreSQL такої команди немає. Але ви можете працювати навколо нього з допомогою методу я описаний деякий час назад для грантів.


Дякую, дуже приємна стаття. Я буду зберігати це як майбутнє посилання. Використовуючи pgAdmin, я завершив резервне копіювання БД, скинувши / видаливши БД, тимчасово надавши new_owner необхідні права, а потім знову створивши та відновивши БД як new_owner, з опцією "немає власника", що перевіряється у вікні відновлення. Це дало результати, які я шукав з новим власником як власником усього.
Кай

Postgres 9.3 ввів команду REASSIGN OWNED. postgresql.org/docs/9.3/sql-reassign-owned.html
Георг Циммер

3

На основі відповіді від 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
$$;

2

Відповідь @Alex Soto є правильною, і суть, яку додав @Yoav Aner, також працює за умови, що в таблиці немає спеціальних символів (імена перегляду (які є законними на постграфах)).

Вам потрібно уникнути їх роботи, і я додав до цього суть: 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 )

Потім передайте файл резервного копіювання назад у PostgreSQL, використовуючи:

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

Оскільки немає власника, то всі створені таблиці, схеми тощо створюються під вказаним вами користувачем для входу.

Я читав, що це може бути хорошим підходом для міграції між версіями PostgreSQL.


2

Я створив для цього зручний сценарій; pg_change_db_owner.sh . Цей скрипт змінює право власності на всі таблиці, представлення, послідовності та функції схеми бази даних, а також власника самої схеми.

Зверніть увагу, що якщо ви хочете просто змінити право власності на всі об'єкти, у певній базі даних, що належать певній ролі бази даних, ви можете просто використовувати команду REASSIGN OWNEDзамість цього.


1

Починаючи з 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_*), але це майже не так часто. Я часто роблю таке:

  1. BEGIN транзакція щодо зміни приват
  2. Змінити право власності на DATABASES на "роль DBA"
  3. Змінити право власності на SCHEMAS на "роль DBA"
  4. REVOKE ALLprivs на всіх TABLES, SEQUENCESіFUNCTIONS від усіх ролей
  5. GRANT SELECT, INSERT, UPDATE, DELETE на відповідних / відповідних таблицях до відповідних ролей
  6. COMMIT транзакція DCL.

1

Прийняте рішення не піклується про право власності на функції. Наступне рішення піклується про все (під час перегляду я помітив, що він схожий на @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};"

1

Наступний простіший скрипт оболонки працював для мене.

#!/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 = до нової схеми.


1

Те саме, що підхід @ 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

0

Докер: змінення власника всіх таблиць + послідовностей

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.