Изменить OWNER для всех таблиц одновременно в PostgreSQL


412

Как изменить владельца всех таблиц в базе данных PostgreSQL?

Я пытался, ALTER TABLE * OWNER TO new_ownerно он не поддерживает синтаксис звездочки.

Ответы:


461

Смотрите 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 идентичны для всех трех.



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 ). Так что, если вы хотите изменить владельца одной базы данных, будьте осторожны!
Кицунэ

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

538

Вы можете использовать REASSIGN OWNEDкоманду.

Сводка:

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

Это изменяет все объекты, принадлежащие old_roleновой роли. Вам не нужно думать о том, какие объекты у пользователя, они все будут изменены. Обратите внимание, что это относится только к объектам внутри одной базы данных. Это не меняет владельца самой базы данных.

Доступно как минимум до 8.2. Их онлайн-документация только заходит так далеко.


ERROR: unexpected classid 3079, Я думаю, что в настоящее время не работает, если есть какие-либо расширения.
Стив Йоргенсен

40
Похоже, что это не работает для пользователей postgres, хотя я подключен к созданной мной базе данных (то есть не к системной базе данных), он говорит следующее: ОШИБКА: не может переназначить владение объектами, принадлежащими роли postgres, поскольку они требуются для базы данных. система
thnee

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

6
Просто чтобы быть понятным, эта команда работает в базе данных, которую вы в настоящее время подключены ТОЛЬКО. Если old_role владеет объектами в нескольких базах данных, вы должны подключиться и выполнить эту команду в каждой из этих баз данных
mavroprovato

11
похоже, это не работает на postgres, размещенном через AWS RDS. Я получаю эту ошибку «Отказано в разрешении на переназначение объектов», и по этой ссылке объясняется, почему: «Похоже, что единственный способ« переназначить принадлежащий »- это использование прав суперпользователя (что противоречит документации), которое недоступно в RDS. ' postgresql-archive.org/…
typoerrpr

198

Это: 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 Владелец базы данных $ DB Владелец $ OWNER;
Йохан Далин

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

ALTER SCHEMA Фред ВЛАДЕЛЕЦ Бетти;
Эрик Алдингер,

21

Мне недавно пришлось сменить владельца всех объектов в базе данных. Хотя таблицы, представления, триггеры и последовательности были несколько легко изменены, вышеупомянутый подход не удался для функций, так как подпись является частью имени функции. Конечно, у меня есть опыт работы с 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это нормально, особенно если вы в любом случае указываете регистр без учета регистра.
Боборт

19

очень просто, попробуйте ...

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

4
Вы можете добавить примечание, что соответствующие строки должны быть скопированы и выполнены. Не то чтобы это не очевидно: p
Nightscape

Который включает в себя удаление всех кавычек вокруг операторов alter .. мульти-курсоры или замена помогают в этом случае.
известноасиля

19

очень просто

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

сделанный.


1
Это, вероятно, делает то, что хотел кверент. Безусловно самый простой.
Geof Sawaya

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) Похоже, что первая и третья строки «ALTER TABLE» являются обманщиками. Это намеренно (например, вам нужно сделать два прохода по столам, чтобы сменить владельца?). 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 такой команды нет. Но вы можете обойти это, используя метод, который я описал некоторое время назад для GRANT.


Спасибо, очень хорошая статья. Я сохраню это в будущем. Используя pgAdmin, я закончил резервное копирование БД, удалив / удалив БД, временно предоставив new_owner необходимые права, а затем заново создав и восстановив БД как new_owner, с опцией «no 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, также работает при условии, что в именах таблиц / представлений нет специальных символов (которые допустимы в postgres).

Вам нужно избежать их на работу, и я загрузил суть для этого: 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.