Как мне изменить владельца всех таблиц в базе данных PostgreSQL?
Я пробовал ALTER TABLE * OWNER TO new_owner
, но он не поддерживает синтаксис asterisk.
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
.
REASSIGN OWNED BY old_role [, ...] TO new_role
Это изменяет все объекты, принадлежащие old_role
, на новую роль. Вам не нужно думать о том, какие объекты у пользователя есть, все они будут изменены. Обратите внимание, что он применяется только к объектам внутри одной базы данных. Он также не изменяет владельца самой базы данных.
Он доступен как минимум до 8.2. Их онлайн-документация идет только дальше.
Это: 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
Мне это нравится, поскольку он изменяет таблицы, представления, последовательностей и функции владельца определенной 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$$;
information_schema.sequences
пусто, хотя SELECT c.* FROM pg_class c WHERE c.relkind = 'S';
списки последовательностей. Почему они могут не совпадать?
очень просто, попробуйте...
select 'ALTER TABLE ' || table_name || ' OWNER TO myuser;' from information_schema.tables where table_schema = 'public';
очень просто
сделано.
Вы можете попробовать следующее в 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 такой команды нет. Но вы можете обойти это, используя метод я описанный некоторое время назад для GRANTs.
В соответствии с ответом от 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 является правильным, а gist, загруженный @Yoav Aner, также работает, если в именах таблиц/представлений нет специальных символов (которые являются законными в postgres).
Вам нужно сбежать от них на работу, и я добавил для этого суть: https://gist.github.com/2911117
То же, что и подход @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
Следующая упрощенная оболочка 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 = для новой схемы.
Ive создал для этого удобный script; pg_change_db_owner.sh. Этот script изменяет право собственности на все таблицы, представления, последовательности и функции в схеме базы данных, а также владелец самой схемы.
Обратите внимание, что если вы хотите просто изменить право собственности на все объекты, в конкретной базе данных,
принадлежащих определенной роли базы данных, тогда вы можете просто использовать команду REASSIGN OWNED
.
Принятое решение не заботится о принадлежности к функциям, следующее решение заботится обо всем (при просмотре я заметил, что он похож на @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};"
Начиная с 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.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.
Мне пришлось изменить владельца таблиц, представлений и последовательностей, и я обнаружил, что отличное решение, опубликованное @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;
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
ALTER TABLE ... OWNER TO
, а неALTER SEQUENCE ...
В случае последовательностей это потому, чтоALTER SEQUENCE ... OWNED BY ...
имеет совершенно другое значение. Опция OWNED BY позволяет связать последовательность с конкретным столбцом таблицы, так что если этот столбец (или вся его таблица) будет удален, последовательность также будет автоматически удалена. ... Указание OWNED BY NONE удаляет любую существующую ассоциацию, делая последовательность «автономной».