pgsql使用积累系列_pg存储过程(函数)创建(以手机号校验为例)

      pg数据库里面没有地道的存储过程(procudure),取而代之的是函数。函数的编写支持多种语言,底层的库函数通常是用C语言编写的,应用级别函数可用sql和pgsql。

下面通过一个通用的手机号清洗的函数,来展示一个函数的级别要素,通用函数构造方案,及postgresql中正则表达式的使用和拼接包含字符串的字符串方法。整个函数的功能,就是通过传入的表名,表主键及需要清洗的手机号字段,将不符合要求的的手机号洗为空字符串,之所以不洗成null,是因为null在有些情况下会给人造成困扰(比如selece带条件比较时数据跟预期不一致),该函数只能解决小写的参数。下面详解

CREATE OR REPLACE FUNCTION "public"."check_phone"("table_name" varchar, "table_id" varchar, "phone" varchar)
  RETURNS "pg_catalog"."void" AS $BODY$

DECLARE
    exec_str VARCHAR(1024);

BEGIN
	RAISE NOTICE 'notice: %', 'begin check';
	exec_str = 'create temp table temp_phone on commit drop as
	select ' || table_id || ',' || '
		case when ' || phone || E' ~ \'^[+]\' then replace(' || phone || E', \'+\', \'00\') else ' || phone || ' end as ' || phone || '
	from ' || table_name || ';' || '

	create temp table temp_phone_1 on commit drop as
	select ' || table_id || ',' || '
		case when ' || phone || E' ~ \'\\D\' then \'\'
			when ' || phone || E' is null then \'\'
			when ' || phone || E' ~ \'^1\' and length(' || phone || ') = 11 then ' || phone || '
			when ' || phone || E'~ \'^01\' and length(' || phone || ') = 12 then ' || phone || '
			when ' || phone || E'~ \'^861\' and length(' || phone || ') = 13 then ' || phone || '
			when ' || phone || E'~ \'00861\' and length(' || phone || ') = 15 then ' || phone || E'
		else \'\' end as ' || phone || '
	from temp_phone;

	update ' || table_name || '  a set ' || phone || ' = t.' || phone || '
	from (select ' || table_id || ', ' || phone || ' from temp_phone_1) t
	where a.' || table_id || ' = t.' || table_id || ';';

	RAISE NOTICE 'notice: %', exec_str;
	execute exec_str;
END;

$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100

CREATE OR REPLACE FUNCTION "public"."check_phone"():在指定的模式下创建一个函数名为check_phone的函数,如果函数已经存在就更新它。

"table_name" varchar, "table_id" varchar, "phone" varchar :函数的参数,默认是in (函数的参数分为in,out,inout,这个大部分关系型数据库都一样)。

RETURNS "pg_catalog"."void":返回类型,在postgres里,一切皆对象,类型和表一样可以自定义,也有对应的模式。

AS :表示下面的内容等价于前面的定义。可以理解成上面是定义,下面是实现。

$BODY$:函数的主题。可以理解成html页面里的body,是实际功能的载体。

DECLARE exec_str VARCHAR(1024) :申明一个待执行的sql字符串。

BEGIN...END:其中的内容在一个事务内。其实有的存储过程不加这个也是可以的,只是多个语句不会在一个事务内执行。

RAISE NOTICE 'notice: %', 'begin check':打印日志,%是占位符。

create temp table temp_phone on commit drop as :创建临时表,并在事务提交时自动删除,as跟上面的AS是一个意思。

E' ~ \'^[+]\' then replace(':E使字符串内的转义字符'\'生效。~ 代表正则表达式,匹配字符串中首字母是'+'的字符串。

E' ~ \'\\D\' then \'\':'\D'匹配一个非数字。

execute exec_str:执行sql串

 LANGUAGE plpgsql:表示用的是pgsql语言。

VOLATILE:表示函数操作对象为最大,即可以操作表,数据库等等。这个是默认值,无需可以配置。如果控制存储过程的使用范围需要调整这个值。

COST 100:这个参数会影响执行计划。也是默认值,不建议修改。

因为postgresql字段区分大小写,而且查询时会将大写字段默认改成小写,如果数据库字段为大写,则会出现找不到字段的错误,所以建议表结构最好用小写,多个单词用下划线连接,而不是用驼峰结构。当然也不是完全解决不了大小写问题的,可以在字段或者表等元素前后加上"号来阻止大写自动转为小写。

下面提供一个同样功能但是能适配大写字段名,表名的函数代码,除了支持大写的情况,这段代码还展示了另一种处理字符拼接中包含字符串的问题,上段代码是通过正则匹配解决,这段代码是通过在原有字符串外再套一层单引号(')解决的。

CREATE OR REPLACE FUNCTION "public"."check_phone"("table_name" varchar, "table_id" varchar, "phone" varchar)
  RETURNS "pg_catalog"."void" AS $BODY$


DECLARE
    exec_str VARCHAR(1024);

BEGIN
	RAISE NOTICE 'notice: %', 'begin check';
	exec_str = 'create temp table temp_phone on commit drop as
	select "' || table_id || '",' || '
		case when "' || phone || '" ~ ''^[+]'' then replace("' || phone || '", ''+'', ''00'') else "' || phone || '" end as "' || phone || '"
	from "' || table_name || '";' || '

	create temp table temp_phone_1 on commit drop as
	select "' || table_id || '",' || '
		case when "' || phone || '" ~ ''\D'' then ''''
			when "' || phone || '" is null then ''''
			when "' || phone || '" ~ ''^1'' and length("' || phone || '") = 11 then "' || phone || '"
			when "' || phone || '" ~ ''^01'' and length("' || phone || '") = 12 then "' || phone || '"
			when "' || phone || '" ~ ''^861'' and length("' || phone || '") = 13 then "' || phone || '"
			when "' || phone || '" ~ ''00861'' and length("' || phone || '") = 15 then "' || phone || '"
		else '''' end as "' || phone || '"
	from temp_phone;

	update "' || table_name || '"  a set "' || phone || '" = t."' || phone || '"
	from (select "' || table_id || '", "' || phone || '" from temp_phone_1) t
	where a."' || table_id || '" = t."' || table_id || '";';

	RAISE NOTICE 'notice: %', exec_str;
	execute exec_str;
END;


$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100

 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果在 PostgreSQL 中使用 `pg_size_pretty` 函数时出现错误,可能是因为该函数不在当前的数据库模式中可用。你可以尝试通过以下两种方式解决问题: 1. 使用完全限定的函数名称:`pg_catalog.pg_size_pretty` 如,将查询语句中的 `pg_size_pretty` 替换为 `pg_catalog.pg_size_pretty`。这将确保使用完整的函数路径,而不仅仅是函数名称。 ```sql SELECT pg_catalog.pg_size_pretty(pg_total_relation_size(current_database())) AS total_size, pg_catalog.pg_size_pretty(pg_database_size(current_database())) AS database_size; ``` 2. 切换到正确的数据库模式 在 PostgreSQL 中,函数可以位于不同的模式中。如果 `pg_size_pretty` 函数位于其他模式中而不是默认的模式中,你需要切换到该模式才能使用它。 首先,可以通过以下查询语句查看函数所在的模式: ```sql SELECT proname, pronamespace::regnamespace AS schema FROM pg_proc WHERE proname = 'pg_size_pretty'; ``` 查询结果将显示函数 `pg_size_pretty` 的模式。然后,你可以使用以下命令切换到正确的模式: ```sql SET search_path TO schema_name; ``` 其中,`schema_name` 是函数所在的模式名称。切换到正确的模式后,你应该能够正常使用 `pg_size_pretty` 函数。 请注意,以上解决方法假设你具有足够的权限来执行这些操作。如果你没有足够的权限或者遇到其他问题,请联系数据库管理员进行进一步的支持和调试。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值