/programming/1348126/modify-owner-on-all-tables-simultaneously-in-postgresql 은 테이블 및 기타 객체를 특정 사용자로 변경하는 멋진 방법을 설명하지만 수영으로 작동합니다. 제안은 내가 만든 기능을 무시하는 것 같습니다.
함수를 포함하여 데이터베이스의 모든 객체 소유자를 재설정하는 매우 쉬운 방법이 있습니까? 손으로하는 것은 매우 바람직하지 않습니다.
/programming/1348126/modify-owner-on-all-tables-simultaneously-in-postgresql 은 테이블 및 기타 객체를 특정 사용자로 변경하는 멋진 방법을 설명하지만 수영으로 작동합니다. 제안은 내가 만든 기능을 무시하는 것 같습니다.
함수를 포함하여 데이터베이스의 모든 객체 소유자를 재설정하는 매우 쉬운 방법이 있습니까? 손으로하는 것은 매우 바람직하지 않습니다.
답변:
정확히 무엇을하고 있는지 알고 있다면 시스템 카탈로그를 직접 조작 해야합니다 . 예기치 않은 부작용이있을 수 있습니다. 또는 복구 할 수없는 데이터베이스 (또는 전체 데이터베이스 클러스터)를 손상시킬 수 있습니다.
Jeremy의 대답 은 기본적으로 트릭을 수행 하지만 일반 대중 에게는 권장되지 않습니다 . 무조건 스키마의 모든 함수를 변경합니다. 영향을받는 시스템 기능이 없거나 추가 모듈에 의해 설치된 기능이 확실하지 않습니까?
지정된 소유자에 이미 속한 함수의 소유자를 변경하는 것도 의미가 없습니다.
먼저, 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
REASSIGN OWNED 명령을 사용할 수 있습니다
수퍼 유저로 데이터베이스에 로그인하고 아래에서 실행하십시오.
REASSIGN OWNED BY [old_user] TO [new_user];
그러면 old_role이 소유 한 테이블, 시퀀스, 함수 등의 모든 개체가 새 역할로 변경됩니다. 사용자가 어떤 종류의 객체를 가지고 있는지 생각할 필요가 없으며 모두 변경됩니다. 이것은 데이터베이스 자체의 소유권을 변경하려는 경우에만 객체를 변경합니다.ALTER DATABASE name OWNER TO new_owner
이것은 루프와 bash 스크립트를 처리하는 대신 n 개의 테이블, 시퀀스가 있기 때문에 가장 좋은 방법입니다
글쎄, 나는 한 단계 프로세스를 찾지 못했지만 데이터베이스에서 볼 수있는 모든 객체를 처리합니다.
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);
pg_proc.proisagg
페이지 (11)의 교체는 릴리스 정보는 말한다 : 시스템 테이블 교체pg_proc
의proisagg
와proiswindow
함께prokind
(피터 Eisentraut)를`