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

344

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

Я пробовал ALTER TABLE * OWNER TO new_owner, но он не поддерживает синтаксис asterisk.

Теги:

20 ответов

386
Лучший ответ

Смотрите 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
  • 1
    Для тех, кто интересуется, почему все 3 являются ALTER TABLE ... OWNER TO , а не ALTER SEQUENCE ... В случае последовательностей это потому, что ALTER SEQUENCE ... OWNED BY ... имеет совершенно другое значение. Опция OWNED BY позволяет связать последовательность с конкретным столбцом таблицы, так что если этот столбец (или вся его таблица) будет удален, последовательность также будет автоматически удалена. ... Указание OWNED BY NONE удаляет любую существующую ассоциацию, делая последовательность «автономной».
Показать ещё 11 комментариев
463

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

Описание:

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

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

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

  • 0
    Это работает именно так, как вы себе представляете. Отлично и спасибо.
  • 17
    ПУТЬ лучшее решение. Это должен быть принятый ответ
Показать ещё 7 комментариев
155

Это: 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 *.*
  • 3
    Очень хорошее решение!
  • 2
    Лучший во всем. Это сработало, приятель.
Показать ещё 4 комментария
39

Если вы хотите сделать это в одном 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, чтобы помочь с этим.

  • 1
    Это гораздо полезнее, поскольку оно меняет владельца всей схемы, включая функции, индексы, последовательности и т. Д. Спасибо!
  • 0
    Это не меняет владельцев схемы. Как поменять владельцев схемы тоже?
Показать ещё 3 комментария
18

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

Мне это нравится, поскольку он изменяет таблицы, представления, последовательностей и функции владельца определенной schema в один раз (в одном 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 и этот ответ by @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$$;
  • 0
    УДИВИТЕЛЬНО! Почему Postgres не добавляет это, я не знаю!
  • 0
    Два вопроса: 1) Похоже, что первая и третья строки «ALTER TABLE» являются обманщиками. Это намеренно (например, вам нужно сделать два прохода по столам, чтобы сменить владельца?). 2) Мы обнаруживаем, что information_schema.sequences пусто, хотя SELECT c.* FROM pg_class c WHERE c.relkind = 'S'; списки последовательностей. Почему они могут не совпадать?
Показать ещё 1 комментарий
16

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

 select 'ALTER TABLE ' || table_name || ' OWNER TO myuser;' from information_schema.tables where table_schema = 'public';
  • 4
    Вы можете добавить примечание, что соответствующие строки должны быть скопированы и выполнены. Не то чтобы это не очевидно: p
  • 0
    Который включает в себя удаление всех кавычек вокруг операторов alter .. мульти-курсоры или замена помогают в этом случае.
14

очень просто

  • su - postgres
  • PSQL
  • REASSIGN, СОБСТВЕННОЕ [old_user] TO [new_user];
  • \c [ваша база данных]
  • REASSIGN, СОБСТВЕННОЕ [old_user] TO [new_user];

сделано.

  • 1
    Это, вероятно, делает то, что хотел кверент. Безусловно самый простой.
  • 1
    Вы только на 4 года опоздали на вечеринку; прокрутить вверх: stackoverflow.com/a/13535184/1772379
9

Вы можете попробовать следующее в 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$$;
7

В PostgreSQL такой команды нет. Но вы можете обойти это, используя метод я описанный некоторое время назад для GRANTs.

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

Вам нужно сбежать от них на работу, и я добавил для этого суть: https://gist.github.com/2911117

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
1

Следующая упрощенная оболочка script работала для меня.

#!/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

Ive создал для этого удобный script; pg_change_db_owner.sh. Этот script изменяет право собственности на все таблицы, представления, последовательности и функции в схеме базы данных, а также владелец самой схемы.

Обратите внимание, что если вы хотите просто изменить право собственности на все объекты, в конкретной базе данных, принадлежащих определенной роли базы данных, тогда вы можете просто использовать команду REASSIGN OWNED.

  • 0
    Прекрасно работает для меня. Это то, что многие будут искать.
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

Начиная с 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 docs на GRANT и REVOKE перейдите к более подробным сведениям об этом. В некоторых ситуациях по-прежнему необходимо использовать трюки с использованием системных каталогов (pg_catalog.pg_*), но это не так часто. Я часто делаю следующее:

  • BEGIN транзакция для изменения привилегий
  • Измените право собственности на DATABASES на роль "DBA"
  • Измените право собственности на SCHEMAS на роль "DBA"
  • REVOKE ALL привилегии для всех TABLES, SEQUENCES и FUNCTIONS из всех ролей
  • GRANT SELECT, INSERT, UPDATE, DELETE в соответствующих/соответствующих таблицах для соответствующих ролей.
  • COMMIT транзакция DCL.
1
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.

0

Мне пришлось изменить владельца таблиц, представлений и последовательностей, и я обнаружил, что отличное решение, опубликованное @rjk, работает нормально, несмотря на одну деталь: если имена объектов имеют смешанный регистр (например, "TableName"), это не удастся с помощью " не найден "-error.
Чтобы обойти это, оберните имена объектов знаком "" "следующим образом:

таблицы

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;
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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню