是否有一种方法可以同时设置PostgreSQL数据库中所有对象的所有者?
-
16-10-2019 - |
题
https://stackoverflow.com/questions/1348126/modify-anderer-one-on-all-tables-simultaney-in-postgresql 描述了一些将表和其他对象更改为特定用户的漂亮方法,并且它可以游泳,但是所有建议似乎都忽略了我创建的功能。
是否有一种相当简单的方法来重置数据库中所有对象的所有者,包括功能?手工做是非常不受欢迎的。
解决方案 5
好吧,我没有找到一个步骤的过程,但是这要照顾我在数据库中看到的所有对象:
update pg_class
SET relowner = (SELECT oid FROM pg_roles WHERE rolname = 'foo')
where relnamespace = (select oid
from pg_namespace
where nspname = 'public'
limit 1);
update pg_proc
set proowner = (select oid from pg_roles where rolname = 'foo')
where pronamespace = (select oid
from pg_namespace
where nspname = 'public'
limit 1);
其他提示
你只应该 操纵系统目录 直接,如果您确切知道自己在做什么。它可能具有意外的副作用。或者,您可能会破坏无法维修的数据库(或整个数据库群集)。
杰里米的回答, ,虽然基本上是在做这个问题,但 不建议 对于公众。它无条件地更改模式中的所有功能。您确定没有受影响的系统功能或其他模块安装的功能?
更改已经属于指定所有者的功能的所有者也毫无意义。
首先,检查是否 REASSIGN OWNED
可以为您工作:
更改数据库角色拥有的数据库对象的所有权
您必须列出所有要明确拒绝的角色。但它 还重新分配功能.
分配 全部 给定模式中的函数(和其他对象)给新所有者(无论以前的所有者如何):
SELECT string_agg('ALTER FUNCTION ' || oid::regprocedure || ' OWNER TO foo;', E'\n') AS ddl
FROM pg_catalog.pg_proc p
JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
WHERE n.nspname = 'public';
-- AND p.relowner <> (SELECT oid FROM pg_roles WHERE rolname = 'foo')
-- AND p.proname ~~ 'f_%'
这会生成 规范SQL命令 ALTER FUNCTION ...
改变 全部 功能(在指定的模式中)。您可以在执行命令之前检查命令 - 一次或全部一个或全部:
ALTER FUNCTION public.bar(text, text) OWNER TO foo;
ALTER FUNCTION public.foo(x integer) OWNER TO foo;
...
我包括一些评论 WHERE
您可能想使用的条款来过滤结果。
演员 regprocedure
用参数产生有效的函数名称,在必要时双重引用,架构 - 在当前必要时符合条件 search_path
.
聚合函数 String_agg() 需要PostgreSQL 9.0或更高版本。在旧版本中替代 array_agg()
和 array_to_string()
.
你 可以 将所有这些放入 DO
语句或此相关答案中所示的功能:
在Postgres中 9.5 或以后,您可以使用新的 对象标识符类型 regnamespace
和 regrole
:
SELECT string_agg('ALTER FUNCTION '|| oid::regprocedure || ' OWNER TO foo;', E'\n') AS ddl
FROM pg_catalog.pg_proc
WHERE pronamespace = 'public'::regnamespace;
-- AND relowner <> 'foo'::regrole
-- AND proname ~~ 'f_%'
我使用此功能来更改表,功能,类型等的所有者。您可以更改光标的查询以适应您的需求。
CREATE OR REPLACE FUNCTION fn_setowner(varchar(50), boolean) RETURNS void AS
$BODY$
DECLARE
p_owner ALIAS FOR $1;
p_debug ALIAS FOR $2;
v_i integer := 0;
v_sql text;
-- CURSORS
-- SCHEMA
pesquemas CURSOR FOR
SELECT quote_ident(schema_name) as nombre_esquema from information_schema.schemata WHERE schema_name NOT LIKE 'pg_%'
and schema_name NOT IN ('information_schema') ORDER BY 1 ASC;
-- TABLE
ptablas CURSOR FOR
SELECT quote_ident(table_schema) || '.' || quote_ident(table_name) as nombre_tabla, * FROM information_schema.tables
WHERE table_schema NOT IN ('pg_catalog', 'information_schema')
AND table_type <> 'FOREIGN TABLE' ORDER BY 1 ASC;
-- FUNCTION
pfunciones CURSOR FOR
SELECT quote_ident(b.nspname) || '.' || quote_ident(a.proname) || '(' || pg_catalog.oidvectortypes(a.proargtypes) || ')' as nombre_function
FROM pg_proc a INNER JOIN pg_namespace b on a.pronamespace = b.oid
WHERE b.nspname NOT IN ('pg_catalog', 'information_schema') AND proisagg = 'f'
AND a.proname not like 'fsym_%' AND a.proname not like 'dblink%' ORDER BY 1 ASC;
-- SEQUENCE
psecuencias CURSOR FOR
SELECT quote_ident(sequence_schema) || '.' || quote_ident(sequence_name) as nombre_secuencia FROM information_schema.sequences
WHERE sequence_schema NOT IN ('pg_catalog', 'information_schema') ORDER BY 1 ASC;
-- TYPE
ptipos CURSOR FOR
SELECT quote_ident(n.nspname) || '.' || quote_ident(t.typname) as nombre_tipo
FROM pg_type t
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
WHERE (t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid))
AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)
AND n.nspname NOT IN ('pg_catalog', 'information_schema') ORDER BY 1 ASC;
BEGIN
-- CHECK LOGIN
IF NOT EXISTS (SELECT 1 FROM pg_user WHERE usename = p_owner) THEN
RAISE EXCEPTION 'Login role not exists --> %', p_owner
USING HINT = 'Please specify correct login and try again.';
END IF;
v_i = 0;
if (p_debug) THEN
RAISE NOTICE '--########## CHANGE SCHEMA OWNER ##########--';
END IF;
FOR resquema IN pesquemas LOOP
v_sql = 'ALTER SCHEMA ' || resquema.nombre_esquema || ' OWNER TO ' || quote_ident(p_owner) || ';';
if (p_debug) THEN RAISE NOTICE '%', v_sql; END IF;
EXECUTE v_sql;
v_i = v_i + 1;
END LOOP;
if (p_debug) THEN
RAISE NOTICE '--@@@@@@ SCHEMAS WITH OWNER % TOTAL = % @@@@@@--', p_owner, CAST(v_i AS VARCHAR);
END IF;
v_i = 0;
if (p_debug) THEN
RAISE NOTICE '--########## CHANGE TABLE OWNER ##########--';
END IF;
FOR rtables IN ptablas LOOP
v_sql = 'ALTER TABLE ' || rtables.nombre_tabla || ' OWNER TO ' || quote_ident(p_owner) || ';';
if (p_debug) THEN RAISE NOTICE '%', v_sql; END IF;
EXECUTE v_sql;
v_i = v_i + 1;
END LOOP;
if (p_debug) THEN
RAISE NOTICE '--@@@@@@ TABLES WITH OWNER % TOTAL = % @@@@@@--', p_owner, CAST(v_i AS VARCHAR);
END IF;
v_i = 0;
if (p_debug) THEN
RAISE NOTICE '--########## CHANGE FUNCTION OWNER ##########--';
END IF;
FOR rfunction IN pfunciones LOOP
v_sql = 'ALTER FUNCTION ' || rfunction.nombre_function || ' OWNER TO ' || quote_ident(p_owner) || ';';
if (p_debug) THEN RAISE NOTICE '%', v_sql; END IF;
EXECUTE v_sql;
v_i = v_i + 1;
END LOOP;
if (p_debug) THEN
RAISE NOTICE '--@@@@@@ FUNCTIONS WITH OWNER % TOTAL = % @@@@@@--', p_owner, CAST(v_i AS VARCHAR);
END IF;
v_i = 0;
if (p_debug) THEN
RAISE NOTICE '--########## CHANGE SEQUENCE OWNER ########## --';
END IF;
FOR rsecuencias IN psecuencias LOOP
v_sql = 'ALTER TABLE ' || rsecuencias.nombre_secuencia || ' OWNER TO ' || quote_ident(p_owner) || ';';
if (p_debug) THEN RAISE NOTICE '%', v_sql; END IF;
EXECUTE v_sql;
v_i = v_i + 1;
END LOOP;
if (p_debug) THEN
RAISE NOTICE '--@@@@@@ SEQUENCES WITH OWNER % TOTAL = % @@@@@@--', p_owner, CAST(v_i AS VARCHAR);
END IF;
v_i = 0;
if (p_debug) THEN
RAISE NOTICE '--########## CHANGE TYPE OWNER ##########--';
END IF;
FOR rtipos IN ptipos LOOP
v_sql = 'ALTER TYPE ' || rtipos.nombre_tipo || ' OWNER TO ' || quote_ident(p_owner) || ';';
if (p_debug) THEN RAISE NOTICE '%', v_sql; END IF;
EXECUTE v_sql;
v_i = v_i + 1;
END LOOP;
if (p_debug) THEN
RAISE NOTICE '--@@@@@@ TYPES WITH OWNER % TOTAL = % @@@@@@--', p_owner, CAST(v_i AS VARCHAR);
END IF;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE
COST 100;
然后我只是执行(如果您想调试输出,只需将第二个参数设置为true):
SELECT fn_setowner('demo', false);
DROP FUNCTION fn_setowner(varchar(30), boolean);
这应该适用于功能:
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
您可以使用重新分配命令
只需使用Superuser登录到数据库,并在下面执行
REASSIGN OWNED BY [old_user] TO [new_user];
这更改了所有对象,即旧_role拥有的表,序列,函数等。您不必考虑用户拥有哪种对象,它们都会全部更改。仅当您想更改该数据库本身的所有权时,才会更改对象 ALTER DATABASE name OWNER TO new_owner
这是最好的方法