1. 程式人生 > 資料庫 >PostgreSQL批量修改函式擁有者的操作

PostgreSQL批量修改函式擁有者的操作

Postgresql如何批量修改函式擁有者,預設建立的函式物件的擁有者為當前建立的使用者,如果使用postgres超級管理員建立一個test()的函式,擁有者就是postgres使用者。下面講解下如何批量修改擁有者。

PostgreSQL批量修改函式擁有者的操作

本文演示的Postgresql版本如下:

PostgreSQL 9.6.8

相關檢視

要查詢Postgresql的函式和函式引數需要使用函式檢視和引數檢視,分別記錄了函式資訊和引數列表資訊。

檢視一: information_schema.routines

檢視routines包含當前資料庫中所有的函式。只有那些當前使用者能夠訪問(作為擁有者或具有某些特權)的函式才會被顯示。需要用到的列如下,完整檢視講解請參考官方文件。

名稱 資料型別 備註
specific_schema sql_identifier 包含該函式的模式名
routine_name sql_identifier 該函式的名字(在過載的情況下可能重複)
specific_name sql_identifier 該函式的"專用名"。這是一個在模式中唯一標識該函式的名稱,即使該函式真正的名稱已經被過載。專用名的格式尚未被定義,它應當僅被用來與指定例程名稱的其他例項進行比較。

檢視二: information_schema.parameters

檢視parameters包含當前資料庫中所有函式的引數的有關資訊。只有那些當前使用者能夠訪問(作為擁有者或具有某些特權)的函式才會被顯示。需要用到的列如下,完整檢視講解請參考官方文件。

名稱 資料型別 備註
parameter_name sql_identifier 引數名,如果引數沒有名稱則為空
udt_name sql_identifier 該引數的資料型別的名字
ordinal_position cardinal_number 該引數在函式引數列表中的順序位置(從 1 開始計數)
specific_name cardinal_number 該函式的"專用名"。詳見第 35.40 節。

注意:可以通過routines. specific_name 和 parameters.specific_name欄位關聯查詢。

單個修改

如果需要修改的函式只有一個,請執行如下SQL語句即可:

如果需要修改的函式只有一個,請執行如下SQL語句即可:

// 無引數函式
ALTER FUNCTION "abc"."test"() OWNER TO "dbadmin";
//帶引數函式
ALTER FUNCTION "abc"."test3"(p1 varchar,p2 varchar) OWNER TO "dbadmin";

批量修改

首先可以查詢當前模式下函式的所有者分別是哪個使用者,使用下面SQL來查詢:

SELECT 
n.nspname as "Schema",p.proname as "Name",pg_catalog.pg_get_function_result(p.oid) as "Result data type",pg_catalog.pg_get_function_arguments(p.oid) as "Argument data types",pg_catalog.pg_get_userbyid(p.proowner) as "Owner"
FROM pg_catalog.pg_proc p
  LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
  LEFT JOIN pg_catalog.pg_language l ON l.oid = p.prolang
WHERE pg_catalog.pg_function_is_visible(p.oid)
  AND n.nspname <> 'pg_catalog'
  AND n.nspname <> 'information_schema'
ORDER BY 1,2;

當前顯示模式“abc”有2個無參函式和1個帶參函式,擁有者都是postgres超級使用者。

PostgreSQL批量修改函式擁有者的操作

然後根據上面講的兩個檢視: routines 和 parameters關聯查詢出模式下的所有函式和引數(目的是為了拼接SQL語句),參考如下:

SELECT 
"routines".specific_schema,"routines".routine_name,COALESCE("parameters".parameter_name,'') AS parameter_name,-- COALESCE返回引數中的第一個非null的值
COALESCE("parameters".udt_name,'') AS udt_name,'') || ' ' || COALESCE("parameters".udt_name,'') AS params,"parameters".ordinal_position 
FROM "information_schema"."routines"
LEFT JOIN "information_schema"."parameters" ON "routines".specific_name="parameters".specific_name 
WHERE "routines".specific_schema='abc' 
ORDER BY 1,2,6;

PostgreSQL批量修改函式擁有者的操作

這裡我們再使用聚合函式: string_agg 把欄位 params所有行連線成字串,並用逗號分隔符分隔。

WITH tmp AS (SELECT 
"routines".specific_schema,6) 
SELECT 
specific_schema,routine_name,string_agg(params,',') AS params,'"'||specific_schema||'"."'||routine_name||'"('||string_agg(params,')||')' AS fname 
FROM tmp GROUP BY specific_schema,routine_name; 

PostgreSQL批量修改函式擁有者的操作

最後使用一個Postgres執行程式碼片段完成批量修改,完整SQL如下:

DO $$
DECLARE r record;
BEGIN
FOR r IN
WITH tmp AS (SELECT 
"routines".specific_schema,6) SELECT '"'||specific_schema||'"."'||routine_name||'"('||string_agg(params,')||')' AS fname FROM tmp GROUP BY specific_schema,routine_name
LOOP
EXECUTE 'ALTER FUNCTION '|| r.fname||' OWNER TO "dbadmin" ';
END LOOP;
END $$;

可以看到模式“abc”的Owner已經全部改為dbadmin這個賬號了。

PostgreSQL批量修改函式擁有者的操作

上次批量修改函式可能存在部分特殊場景會報錯, 會把“引數型別” + “返回型別” 拼接在一起

改進方法:我們通過pg_catalog目錄來實現批量修改,參考程式碼如下:

DO $$
DECLARE r record;
BEGIN
FOR r IN
 WITH tmp AS (
 SELECT n.nspname as "Schema",CASE
 WHEN p.proisagg THEN 'agg'
 WHEN p.proiswindow THEN 'window'
 WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN 'trigger'
 ELSE 'normal'
 END as "Type"
 FROM pg_catalog.pg_proc p
  LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
 WHERE n.nspname = 'etl'
 ORDER BY 1,4
 ) SELECT '"' || "Schema" || '"' || '.' || '"' || "Name" || '"' || '(' || "Argument data types" ||')' AS fname FROM tmp
LOOP
EXECUTE 'ALTER FUNCTION '|| r.fname||' OWNER TO "postgres" ';
END LOOP;
END $$;

補充:PostgreSQL更改Owner所有者

網上一個大神寫的

SELECT
‘alter table ' || nsp.nspname || ‘.' || cls.relname || ' owner to usr_zhudong;' || chr ( 13 )
FROM
pg_catalog.pg_class cls,pg_catalog.pg_namespace nsp
WHERE
nsp.nspname IN ( ‘public' )
AND cls.relnamespace = nsp.oid
AND cls.relkind = ‘r'
ORDER BY
nsp.nspname,cls.relname;

我來做一個改版

SELECT
'alter table ' || nsp.nspname || '.' || cls.relname || ' owner to test2;' || chr ( 13 )
FROM
pg_catalog.pg_class cls,pg_catalog.pg_namespace nsp
WHERE
nsp.nspname IN ( 'public' )
AND cls.relnamespace = nsp.oid
AND cls.relkind = 'r'
ORDER BY
nsp.nspname,cls.relname;
 
SELECT
'alter table "' || nsp.nspname || '"."' || cls.relname || '" owner to user01;' || chr ( 13 )
FROM
pg_catalog.pg_class cls,cls.relname;

效果:

PostgreSQL批量修改函式擁有者的操作

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援我們。如有錯誤或未考慮完全的地方,望不吝賜教。