PostgreSQL的函数及存储过程的基本使用

  新人刚接触PostgreSQL数据库,在这里总结了一下存储过程中我用到了的基础知识,常常温习。

postgre数据库安装、卸载、重新安装以及pgAdmin的基本使用详见 上一篇


零、存储过程与函数的异同

  • 函数通常用于对一个或多个输入参数进行操作,主要目的是返回一个结果值;而存储过程通常包含一系列的SQL语句或其他代码块,主要目的是执行一系列的操作。
  • 函数可以被用于查询中的SELECT语句中的列表达式的一部分;而存储过程通常在PL/pgSQL代码块中运行,不能作为查询的一部分。
  • 函数可以在SELECT、UPDATE、DELETE等SQL语句中被使用;而存储过程不能直接被用于SQL语句中。
  • 函数可以有返回值;而存储过程通常没有明确的返回值,若一定需要返回值则需要使用OUT关键字。
  • 分支选择、循环等流程语句的使用方法是一致的。

一、编码结构

1.函数的结构

例: 一个求长方形面积的函数

create or replace function area_of_rectangle(lenth integer,height integer)
returns integer as
$$
declare
	area integer := 0;
begin
	area := lenth * height;
	return area;
end
$$
language 'plpgsql';

说明:

  • 第一行 用于声明函数名及需要的参数。需要注意参数格式:(变量名1 变量类型 , 变量名2 变量类型,…)
  • 第二行 声明返回值的类型。注意这里是returns,有“s”!!!
  • 第三行 两个美元符中间可以填入符合命名规则的任意字符,如$body$、$aaaa$。但是下方的美元符必须与这里的保持一致。
  • 第四行 declare表示声明变量,可以声明多个变量。
  • 第五行 声明了一个integer类型的变量并赋了初始值。
  • 第六行 begin表示语句开始
  • 第七行 计算长方形的面积
  • 第八行 将值返回
  • 第九行 end表示语句结束
  • 第十一行 声明该存储过程使用的语言。有时遇到编译报错可能是这里写成了’sql’。

调用存储过程:

select area_of_rectangle(5,9);

结果截图:
在这里插入图片描述

2.存储过程的结构

例: 一个求长方体体积的存储过程。(这个存储过程的内容毫无意义,它更适合定义为函数。这里只是用它来说明存储过程的结构,并且可以自行对比与函数的异同)

CREATE PROCEDURE volume_of_cuboid(lenth integer,width integer,height integer, OUT volume integer)
LANGUAGE plpgsql AS
$$
DECLARE
	area integer := 0;
BEGIN
    area := lenth * width;
    volume := area * height;
END;
$$

说明:

  • 第一行 用于声明存储过程的名称及需要的入参、出参。需要注意参数格式:(变量名1 变量类型 , 变量名2 变量类型,…)。并且需要用OUT关键字来标记出参,如果自定义的存储过程不需要出参则不定义即可。
  • 第二行 声明该存储过程使用的语言
  • 第三行 两个美元符中间可以填入符合命名规则的任意字符,如$body$、$aaaa$。但是下方的美元符必须与这里的保持一致。
  • 第四行 declare表示声明变量,可以声明多个变量。
  • 第五行 声明了一个integer类型的变量“面积”并赋了初始值0。
  • 第六行 begin表示语句开始
  • 第七行 计算长方体底面的面积
  • 第八行 计算长方体的体积
  • 第九行 end表示语句结束

调用存储过程:

CALL volume_of_cuboid(10, 20, 30 total);
-- 或
SELECT * FROM volume_of_cuboid(10, 20, 30);

二、变量使用

1.变量类型

存储过程中,对变量赋值需要两个值类型一致,如经常碰到bigint类型值赋值到integer变量中,导致运行报错。我用过的类型:

类型说明备注
character varying(n)变长的字符串类型在存储过程中不常用
text不限长度的字符串类型字符串类型用这个简单方便快捷
integer4字节整型
bigint8字节整形count(*)函数的查询值属于此类型
numeric(m,n)精确的小数类型
date日期类型
time时间类型
record记录类型若存储过程需要返回多行多列记录,可以用这个

更多详细变量类型可参考菜鸟教程学习:
https://www.runoob.com/postgresql/postgresql-data-type.html

2.record变量

  record类型变量是“记录类型”的变量,用于存储多行多列的值。
  按官方文档的说明,record类型的变量并不是真正的变量,该类型变量在第一次赋值前,它有多少列、每一列是什么类型都是不确定的。在第一次赋值后,该变量就根据值自动确定列的数量和各列的类型。

3.赋值

静态赋值:

student_name := '张静';

动态赋值:

select name into student_name from class where stu_No = 1;
--或者
execute 'select name from class where stu_No = 1' into student_name;

注意 “:=”“into” 是关键。


三、基本流程语句

1.分支选择

if语句:

IF ... THEN ... END IF;
IF ... THEN ... ELSE ... END IF;
IF ... THEN ... ELSE ... THEN ... ELSE ... END IF;
--例:
if student_name = '张静' then
	RAISE NOTICE '我是张静';
else if student_name like '%李%' then
	RAISE NOTICE '我姓李';
else
	RAISE NOTICE '我不是张静,也不姓李';
end if;

case语句:

CASE ... WHEN ... THEN ... ELSE ... END CASE;
CASE WHEN ... THEN ... ELSE ... END CASE;
--例:
case student_name when '张静','晓静' then
	RAISE NOTICE '张静和晓静都是我的名称';
else 
	RAISE NOTICE '你叫错名字了';
end case;
--例:
case when student_name = '张静' or student_name = '晓静' then
	RAISE NOTICE '张静和晓静都是我的名称';
else
	RAISE NOTICE '你叫错名字了';
end case;

2.循环

简单循环 中括号为可选项

[ <<label>> ]
LOOP
    循环体语句;
    EXIT [ label ] [ WHEN 判断条件表达式 ];
END LOOP [ label ];

--例-计算1到100的和:
sum := 0;
i := 0;
loop
	i := i + 1;
	sum := sum + i;
	exit when i = 100 ;
end loop;
RAISE NOTOCE '1到100的和为:%',sum;

while循环

[ <<label>> ]
WHILE 判断条件表达式 LOOP
    循环体语句;
END LOOP [ label ];

--例 - 计算1到100的和:
sum := 0;
i := 1;
while i<=100 loop
	sum := sum + i;
	i := i + 1;
end loop
RAISE NOTOCE '1到100的和为:%',sum;

for循环

[ <<label>> ]
FOR 循环控制变量 IN [ REVERSE ] 循环范围 [ BY expression ] LOOP
    循环体语句;
END LOOP [ label ];

--计算1到100的和:
--例1 - 循环执行过程类似于:for(i=1;i<=100;i++){}
sum := 0;
for i in 1..100 loop
	sum := sum + i;
end loop;
RAISE NOTOCE '1到100的和为:%',sum;

--例2 - 循环执行过程类似于:for(i=100;i>=1;i--){}
sum := 0;
for i in REVERSE 100..1 loop
	sum := sum + i;
end loop;
RAISE NOTOCE '1到100的和为:%',sum;

--计算1到100之间所有奇数的和
--例3 - 循环执行过程类似于:for(i=1;i<=100;i=i+2){}
sum := 0;
for i in 1..100 by 2 loop
	sum := sum + i;
end loop;
RAISE NOTOCE '1到100的和为:%',sum;

for遍历查询的结果集

[ <<label>> ]
FOR 变量 IN 查询语句 LOOP
    循环体语句;
END LOOP [ label ];

--例 - 遍历班级中每个人的名字:
for student_name in select name from class loop
	RAISE NOTICE '姓名:%',student_name;
end loop;

四、查询并返回多条记录

---- postgreSQL使用存储过程查询并显示多行多列数据 ----
---- 参考网址:https://blog.csdn.net/wuyilun2013/article/details/42779345

create or replace function f_get_member_info(id integer)
returns setof record as --setof是关键字,暂时不清楚其作用;record是返回的数据类型,即“记录类型”数据;
$$--两个美元符必须存在,中间可以填入符合命名规则的字符(如$body$,$abc$),但必须与下方的两个美元符相统一
declare
	rec record;--定义记录类型的变量,用于存储查询的结果
begin
	--开始for循环,执行SELECT语句。注意,第一个loop后没有分号!
	for rec in EXECUTE 'SELECT id,real_name FROM a_account_all' loop
		return next rec;--将查询结果依次追加到rec变量中
	end loop;--for循环结束
	return;
end
$$
language 'plpgsql';

--调用存储过程f_get_member_info示例
-- a_account_all 为存储过程中被查询的表,id和real_name是表中的字段,也是在存储过程中被查询的字段
SELECT * FROM f_get_member_info(1568) as a_account_all(id integer,real_name character varying(50));

五、其它

1、存储过程中,使用RAISE NOTICE可以在运行时将变量输出显示,可用于查看循环执行情况等。如下语句中,单引号内为输出内容,%表示变量值,loop_count为要输出显示的变量。这种输出格式与C语言中的printf()有点像。

	RAISE NOTICE '---- 已执行 % 个账号',loop_count;

2、如果存储过程编译时,一直只提示有语法错误,没有说明咋样的错误,那么先检查语言是否为plpgsql。若语言没有错误,则仔细检查begin与end之间的语句是否正确,如嵌套选择和嵌套循环是否都有对应的END

3、record变量使用示例:

-- FUNCTION: public.test()

-- DROP FUNCTION public.test();

CREATE OR REPLACE FUNCTION public.test()
    RETURNS SETOF record 
    LANGUAGE 'plpgsql'
	
	--这三句话我也还没搞懂其含义,但加上不会报错
    COST 100
    VOLATILE 
    ROWS 1000
    
AS $BODY$
DECLARE
	temp_rec record ;--第一个记录集
	rec record ;--第二个记录集
BEGIN
	--给第一个结果集赋值
	for temp_rec in execute 'SELECT 1,2,3' loop
		return next temp_rec;
		RAISE NOTICE 'temp_rec:%',temp_rec;
	end loop;
	
	--给第二个结果集赋值
	for rec in execute 'SELECT 4,5,6' loop
		return next rec;
		RAISE NOTICE 'rec:%',rec;
	end loop;
	
	--给第二个结果集追加值
	rec := (9,8,7);
	return next rec;
	
	--将两个结果集一起返回
	return ;
END
$BODY$;

ALTER FUNCTION public.test()
    OWNER TO postgres;

调用示例:
SELECT * FROM test() as temp1(num_1 integer,num_2 integer,num_3 integer);
  • 51
    点赞
  • 258
    收藏
    觉得还不错? 一键收藏
  • 25
    评论
### 回答1: MySQL和PostgreSQL存储过程中对变量使用的区别主要体现在语法上。 MySQL中使用DECLARE语句定义变量,并使用SET语句赋值。例如: ``` DECLARE var_name INT; SET var_name = 5; ``` PostgreSQL使用DECLARE语句定义变量,并使用:=赋值。例如: ``` DECLARE var_name INT; var_name := 5; ``` 在MySQL中,存储过程语言和SQL语言比较相似,它支持循环、判断和游标等结构。而PostgreSQL存储过程语言比较类似于PL/SQL语言,支持块级结构和异常处理。 总的来说, 两者都可以实现相同的功能,但是使用语法不同。 ### 回答2: MySQL和PostgreSQL是两种常见的关系型数据库,它们在存储过程中对变量使用的方式有一些区别。 在MySQL中,变量定义使用的是DECLARE关键字。在存储过程中,可以使用用户自定义变量,通过声明变量名和类型来定义。变量在DECLARE语句之后进行初始化,在存储过程中可以使用SET语句来赋值或修改变量的值。MySQL的存储过程中,变量的作用域只在当前存储过程内。 而在PostgreSQL中,变量定义使用的是简单的:=运算符。在存储过程中,可以使用PL/pgSQL语法创建和使用变量。变量在声明时可以指定类型,也可以根据赋值的情况自动推断类型。在存储过程中,变量的作用域可以是整个函数块,也可以是函数内的一个特定区域。 此外,PostgreSQL还支持更复杂的数据类型,如数组和记录类型,并且可以在存储过程使用这些类型的变量。而MySQL对于存储过程中的变量类型支持相对简单,通常只支持基本的数值和字符串类型。 总结来说,MySQL和PostgreSQL存储过程中对变量的使用方式有些许差异。MySQL使用DECLARE关键字进行变量定义,变量的作用域只在当前存储过程内;而PostgreSQL使用简单的:=运算符进行变量定义,变量的作用域可以是整个函数块。此外,PostgreSQL还支持更复杂的数据类型,而MySQL对于变量类型的支持相对较简单。 ### 回答3: MySQL和PostgreSQL存储过程上对变量使用的区别有以下几点: 1. 变量类型:MySQL支持多种类型的变量,包括整数、浮点数、字符串、日期等,可以直接定义和使用;而PostgreSQL则需要使用特殊的语法来声明和使用变量。 2. 变量作用域:MySQL的存储过程中的变量作用域只限于当前会话,即在存储过程中声明的变量只在该存储过程中有效;而PostgreSQL存储过程中的变量作用域可以更广泛,可以在整个函数体内部使用。 3. 变量赋值:MySQL中可以使用SET语句来给变量赋值,也可以在声明变量时直接赋初值;而在PostgreSQL中,需要使用SELECT INTO语句或者使用:=运算符来给变量赋值。 4. 变量引用:MySQL中可以直接使用变量名进行引用,类似于普通的变量使用;而在PostgreSQL中,需要使用特殊的语法来引用变量,以区分普通的列名或者字段名。 5. 变量作为参数传递:在MySQL中,存储过程的参数可以直接使用变量来代替;而在PostgreSQL中,需要使用特殊的语法来传递和使用变量作为参数。 综上所述,MySQL和PostgreSQL存储过程上对变量使用的区别主要体现在变量类型、作用域、赋值、引用和作为参数传递等方面。了解这些差异有助于开发人员在使用存储过程时正确、高效地使用变量。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值