PostgreSQL批量修改函数拥有者的操作

 更新时间:2021年1月4日 14:49  点击:1986

Postgresql如何批量修改函数拥有者,默认创建的函数对象的拥有者为当前创建的用户,如果使用postgres超级管理员创建一个test()的函数,拥有者就是postgres用户。下面讲解下如何批量修改拥有者。

本文演示的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超级用户。

然后根据上面讲的两个视图: 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".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;

这里我们再使用聚合函数: string_agg 把字段 params所有行连接成字符串,并用逗号分隔符分隔。

WITH tmp AS (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".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; 

最后使用一个Postgres执行代码片段完成批量修改,完整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返回参数中的第一个非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已经全部改为dbadmin这个账号了。

上次批量修改函数可能存在部分特殊场景会报错, 会把“参数类型” + “返回类型” 拼接在一起

改进方法:我们通过pg_catalog目录来实现批量修改,参考代码如下:

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 $$;

补充: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,
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;

效果:

以上为个人经验,希望能给大家一个参考,也希望大家多多支持猪先飞。如有错误或未考虑完全的地方,望不吝赐教。

[!--infotagslink--]

相关文章

  • php正确禁用eval函数与误区介绍

    eval函数在php中是一个函数并不是系统组件函数,我们在php.ini中的disable_functions是无法禁止它的,因这他不是一个php_function哦。 eval()针对php安全来说具有很...2016-11-25
  • php中eval()函数操作数组的方法

    在php中eval是一个函数并且不能直接禁用了,但eval函数又相当的危险了经常会出现一些问题了,今天我们就一起来看看eval函数对数组的操作 例子, <?php $data="array...2016-11-25
  • Python astype(np.float)函数使用方法解析

    这篇文章主要介绍了Python astype(np.float)函数使用方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-06-08
  • PostgreSQL判断字符串是否包含目标字符串的多种方法

    这篇文章主要介绍了PostgreSQL判断字符串是否包含目标字符串的多种方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-02-23
  • Python中的imread()函数用法说明

    这篇文章主要介绍了Python中的imread()函数用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-16
  • C# 中如何取绝对值函数

    本文主要介绍了C# 中取绝对值的函数。具有很好的参考价值。下面跟着小编一起来看下吧...2020-06-25
  • C#学习笔记- 随机函数Random()的用法详解

    下面小编就为大家带来一篇C#学习笔记- 随机函数Random()的用法详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • PostgreSQL TIMESTAMP类型 时间戳操作

    这篇文章主要介绍了PostgreSQL TIMESTAMP类型 时间戳操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-12-26
  • postgresql 实现多表关联删除

    这篇文章主要介绍了postgresql 实现多表关联删除操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-02
  • 金额阿拉伯数字转换为中文的自定义函数

    CREATE FUNCTION ChangeBigSmall (@ChangeMoney money) RETURNS VarChar(100) AS BEGIN Declare @String1 char(20) Declare @String2 char...2016-11-25
  • Postgresql 如何选择正确的关闭模式

    这篇文章主要介绍了Postgresl 如何选择正确的关闭模式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-18
  • Android开发中findViewById()函数用法与简化

    findViewById方法在android开发中是获取页面控件的值了,有没有发现我们一个页面控件多了会反复研究写findViewById呢,下面我们一起来看它的简化方法。 Android中Fin...2016-09-20
  • C++中 Sort函数详细解析

    这篇文章主要介绍了C++中Sort函数详细解析,sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变...2022-08-18
  • PHP用strstr()函数阻止垃圾评论(通过判断a标记)

    strstr() 函数搜索一个字符串在另一个字符串中的第一次出现。该函数返回字符串的其余部分(从匹配点)。如果未找到所搜索的字符串,则返回 false。语法:strstr(string,search)参数string,必需。规定被搜索的字符串。 参数sea...2013-10-04
  • postgresql数据添加两个字段联合唯一的操作

    这篇文章主要介绍了postgresql数据添加两个字段联合唯一的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-02-04
  • PHP函数分享之curl方式取得数据、模拟登陆、POST数据

    废话不多说直接上代码复制代码 代码如下:/********************** curl 系列 ***********************///直接通过curl方式取得数据(包含POST、HEADER等)/* * $url: 如果非数组,则为http;如是数组,则为https * $header:...2014-06-07
  • php中的foreach函数的2种用法

    Foreach 函数(PHP4/PHP5)foreach 语法结构提供了遍历数组的简单方式。foreach 仅能够应用于数组和对象,如果尝试应用于其他数据类型的变量,或者未初始化的变量将发出错误信息。...2013-09-28
  • C语言中free函数的使用详解

    free函数是释放之前某一次malloc函数申请的空间,而且只是释放空间,并不改变指针的值。下面我们就来详细探讨下...2020-04-25
  • PHP函数strip_tags的一个bug浅析

    PHP 函数 strip_tags 提供了从字符串中去除 HTML 和 PHP 标记的功能,该函数尝试返回给定的字符串 str 去除空字符、HTML 和 PHP 标记后的结果。由于 strip_tags() 无法实际验证 HTML,不完整或者破损标签将导致更多的数...2014-05-31
  • SQL Server中row_number函数的常见用法示例详解

    这篇文章主要给大家介绍了关于SQL Server中row_number函数的常见用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-12-08