PostgreSQL批量修改函數(shù)擁有者的操作
Postgresql如何批量修改函數(shù)擁有者,默認(rèn)創(chuàng)建的函數(shù)對(duì)象的擁有者為當(dāng)前創(chuàng)建的用戶,如果使用postgres超級(jí)管理員創(chuàng)建一個(gè)test()的函數(shù),擁有者就是postgres用戶。下面講解下如何批量修改擁有者。

本文演示的Postgresql版本如下:
PostgreSQL 9.6.8
相關(guān)視圖
要查詢Postgresql的函數(shù)和函數(shù)參數(shù)需要使用函數(shù)視圖和參數(shù)視圖,分別記錄了函數(shù)信息和參數(shù)列表信息。
視圖一: information_schema.routines
視圖routines包含當(dāng)前數(shù)據(jù)庫(kù)中所有的函數(shù)。只有那些當(dāng)前用戶能夠訪問(wèn)(作為擁有者或具有某些特權(quán))的函數(shù)才會(huì)被顯示。需要用到的列如下,完整視圖講解請(qǐng)參考官方文檔。
| 名稱 | 數(shù)據(jù)類型 | 備注 |
|---|---|---|
| specific_schema | sql_identifier | 包含該函數(shù)的模式名 |
| routine_name | sql_identifier | 該函數(shù)的名字(在重載的情況下可能重復(fù)) |
| specific_name | sql_identifier | 該函數(shù)的"專用名"。這是一個(gè)在模式中唯一標(biāo)識(shí)該函數(shù)的名稱,即使該函數(shù)真正的名稱已經(jīng)被重載。專用名的格式尚未被定義,它應(yīng)當(dāng)僅被用來(lái)與指定例程名稱的其他實(shí)例進(jìn)行比較。 |
視圖二: information_schema.parameters
視圖parameters包含當(dāng)前數(shù)據(jù)庫(kù)中所有函數(shù)的參數(shù)的有關(guān)信息。只有那些當(dāng)前用戶能夠訪問(wèn)(作為擁有者或具有某些特權(quán))的函數(shù)才會(huì)被顯示。需要用到的列如下,完整視圖講解請(qǐng)參考官方文檔。
| 名稱 | 數(shù)據(jù)類型 | 備注 |
|---|---|---|
| parameter_name | sql_identifier | 參數(shù)名,如果參數(shù)沒(méi)有名稱則為空 |
| udt_name | sql_identifier | 該參數(shù)的數(shù)據(jù)類型的名字 |
| ordinal_position | cardinal_number | 該參數(shù)在函數(shù)參數(shù)列表中的順序位置(從 1 開(kāi)始計(jì)數(shù)) |
| specific_name | cardinal_number | 該函數(shù)的"專用名"。詳見(jiàn)第 35.40 節(jié)。 |
注意:可以通過(guò)routines. specific_name 和 parameters.specific_name字段關(guān)聯(lián)查詢。
單個(gè)修改
如果需要修改的函數(shù)只有一個(gè),請(qǐng)執(zhí)行如下SQL語(yǔ)句即可:
如果需要修改的函數(shù)只有一個(gè),請(qǐng)執(zhí)行如下SQL語(yǔ)句即可:
// 無(wú)參數(shù)函數(shù) ALTER FUNCTION "abc"."test"() OWNER TO "dbadmin"; //帶參數(shù)函數(shù) ALTER FUNCTION "abc"."test3"(p1 varchar, p2 varchar) OWNER TO "dbadmin";
批量修改
首先可以查詢當(dāng)前模式下函數(shù)的所有者分別是哪個(gè)用戶,使用下面SQL來(lái)查詢:
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;
當(dāng)前顯示模式“abc”有2個(gè)無(wú)參函數(shù)和1個(gè)帶參函數(shù),擁有者都是postgres超級(jí)用戶。

然后根據(jù)上面講的兩個(gè)視圖: routines 和 parameters關(guān)聯(lián)查詢出模式下的所有函數(shù)和參數(shù)(目的是為了拼接SQL語(yǔ)句),參考如下:
SELECT
"routines".specific_schema,
"routines".routine_name,
COALESCE("parameters".parameter_name, '') AS parameter_name, -- COALESCE返回參數(shù)中的第一個(gè)非null的值
COALESCE("parameters".udt_name, '') AS udt_name,
COALESCE("parameters".parameter_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;

這里我們?cè)偈褂镁酆虾瘮?shù): string_agg 把字段 params所有行連接成字符串,并用逗號(hào)分隔符分隔。
WITH tmp AS (SELECT
"routines".specific_schema,
"routines".routine_name,
COALESCE("parameters".parameter_name, '') AS parameter_name, -- COALESCE返回參數(shù)中的第一個(gè)非null的值
COALESCE("parameters".udt_name, '') AS udt_name,
COALESCE("parameters".parameter_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)
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;

最后使用一個(gè)Postgres執(zhí)行代碼片段完成批量修改,完整SQL如下:
DO $$
DECLARE r record;
BEGIN
FOR r IN
WITH tmp AS (SELECT
"routines".specific_schema,
"routines".routine_name,
COALESCE("parameters".parameter_name, '') AS parameter_name, -- COALESCE返回參數(shù)中的第一個(gè)非null的值
COALESCE("parameters".udt_name, '') AS udt_name,
COALESCE("parameters".parameter_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) 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已經(jīng)全部改為dbadmin這個(gè)賬號(hào)了。

上次批量修改函數(shù)可能存在部分特殊場(chǎng)景會(huì)報(bào)錯(cuò), 會(huì)把“參數(shù)類型” + “返回類型” 拼接在一起
改進(jìn)方法:我們通過(guò)pg_catalog目錄來(lái)實(shí)現(xiàn)批量修改,參考代碼如下:
DO $$
DECLARE r record;
BEGIN
FOR r IN
WITH tmp AS (
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",
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, 2, 4
) SELECT '"' || "Schema" || '"' || '.' || '"' || "Name" || '"' || '(' || "Argument data types" ||')' AS fname FROM tmp
LOOP
EXECUTE 'ALTER FUNCTION '|| r.fname||' OWNER TO "postgres" ';
END LOOP;
END $$;
補(bǔ)充:PostgreSQL更改Owner所有者
網(wǎng)上一個(gè)大神寫(xiě)的
SELECT ‘a(chǎn)lter 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;
我來(lái)做一個(gè)改版
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, 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;
效果:

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
- Postgresql去重函數(shù)distinct的用法說(shuō)明
- PostgreSQL 定義返回表函數(shù)的操作
- PostgreSQL的generate_series()函數(shù)的用法說(shuō)明
- postgresql合并string_agg函數(shù)的實(shí)例
- PostgreSQL數(shù)據(jù)類型格式化函數(shù)操作
- 在postgresql數(shù)據(jù)庫(kù)中判斷是否是數(shù)字和日期時(shí)間格式函數(shù)操作
- Postgresql自定義函數(shù)詳解
- postgresql 循環(huán)函數(shù)的簡(jiǎn)單實(shí)現(xiàn)操作
相關(guān)文章
PostgreSQL截取字符串到指定字符位置詳細(xì)示例
這篇文章主要給大家介紹了關(guān)于PostgreSQL截取字符串到指定字符位置的相關(guān)資料,PostgreSQL數(shù)據(jù)庫(kù)拼接字符串函數(shù)是一種非常重要的函數(shù),使用它可以方便地將不同的字符串進(jìn)行拼接操作,從而得到我們需要的結(jié)果,需要的朋友可以參考下2023-07-07
將PostgreSQL的數(shù)據(jù)實(shí)時(shí)同步到Doris的技巧分享
眾所周知,在兩個(gè)毫不相干的數(shù)據(jù)管理系統(tǒng)之間進(jìn)行數(shù)據(jù)同步,特別是實(shí)時(shí)同步,其復(fù)雜程度足以讓高級(jí)DBA腦瓜疼,本文給大家介紹了將PostgreSQL的數(shù)據(jù)實(shí)時(shí)同步到Doris的技巧分享,需要的朋友可以參考下2024-03-03
PostgreSQL 重復(fù)數(shù)據(jù)處理的操作方法
這篇文章主要介紹了PostgreSQL 重復(fù)數(shù)據(jù)處理的操作方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12
Postgresql ALTER語(yǔ)句常用操作小結(jié)
這篇文章主要介紹了Postgresql ALTER語(yǔ)句常用操作小結(jié),本文講解了增加一列、刪除一列、更改列的數(shù)據(jù)類型、表的重命名、更改列的名字、字段的not null設(shè)置等常用操作的代碼示例,需要的朋友可以參考下2015-06-06
PostgreSQL教程(十九):SQL語(yǔ)言函數(shù)
這篇文章主要介紹了PostgreSQL教程(十九):SQL語(yǔ)言函數(shù),本文講解了SQL語(yǔ)言函數(shù)基本概念、基本類型、復(fù)合類型、帶輸出參數(shù)的函數(shù)、返回結(jié)果作為表數(shù)據(jù)源等內(nèi)容,需要的朋友可以參考下2015-05-05
PostgreSQL處理數(shù)據(jù)并發(fā)更新沖突的解決方法
在數(shù)據(jù)庫(kù)并發(fā)操作環(huán)境中,多個(gè)事務(wù)同時(shí)嘗試更新相同的數(shù)據(jù)可能導(dǎo)致沖突,PostgreSQL?提供了一系列機(jī)制來(lái)處理這些并發(fā)更新沖突,以確保數(shù)據(jù)的一致性和完整性,所以本文給大家介紹了PostgreSQL處理數(shù)據(jù)并發(fā)更新沖突的解決方法,需要的朋友可以參考下2024-07-07

