存储过程和函数的区别

目录

零、基本格式

一、返回值

二、参数传递

1、存储过程

2、函数

三、执行方式

四、事务处理

1、存储过程

2、函数

五、数据库兼容性


课上老师提出的讨论题:存储过程和函数的区别?

有同学回复:在数据库后端编程中,存储过程和函数都是用来封装一段可重复使用的代码逻辑,以便在需要时进行调用。

它们的主要区别在于:

  1. 返回值:函数必须返回一个值,可以是一个标量值或一个表值,而存储过程不需要返回值,只需要执行一些操作。
  2. 参数传递:函数和存储过程都可以接受参数,但是函数的参数只能是输入参数,而存储过程可以有输入参数、输出参数和输入输出参数。
  3. 执行方式:函数可以像普通的SQL语句一样直接调用执行,而存储过程需要用CALL或EXECUTE语句来调用执行。
  4. 事务处理:存储过程可以控制事务处理,可以在存储过程内部开启、提交或回滚事务,而函数无法控制事务。
  5. 数据库兼容性:函数在不同的数据库系统之间具有更好的兼容性,而存储过程在不同的数据库系统之间可能存在差异。

在零部分之后我们将对这段话进行验证,但仅针对于 PostgreSQL15 数据库。

零、基本格式

函数的基本格式:

create function func()
returns void as $$
    begin
        
    end;
$$
language plpgsql;

存储过程的基本格式:

create procedure pro()
as $$
    begin
        
    end;
$$
language plpgsql;

运行结果如下图所示:

存储过程和函数的区别_第1张图片

显然我们会认为存储过程和函数是两个玩意儿,但是 PostgreSQL15 仍然不允许存储过程和函数的 “函数类型” 相同,函数类型包括:函数名和参数类型,否则出现下述报错:

ERROR: 错误:  带相同参数类型的函数 "func" 已经存在

SQL 状态: 42723

 

 

一、返回值

验证成立:

  • 函数必须要有一个返回值,可以是一个标量值或一个表值
  • 存储过程不能有返回值

不满足上述条件则会报错。

二、参数传递

验证失败,第二句话错误:

  • 函数和存储过程都可以接受参数 √
  • 函数的参数只能是输入参数 × => 可以是输入参数和输出参数
  • 存储过程的参数可以是输入参数和输出参数 √

默认为输入参数,具有 OUT 关键字的是输出参数。

1、存储过程

create or replace procedure test(a integer, out b integer)
as $$
    begin
        b := a * 2;
    end;
$$
language plpgsql;

调用方法:

call test(5, 0);

看起来是不是很离谱,似乎输出参数也可以填一个字段,但是我不知道格式是啥。

2、函数

create or replace function testf(a integer, out b integer)
returns integer as $$
    begin
        b := a * 2;
    end;
$$
language plpgsql;

注意点一:返回值由 OUT 参数决定

-- 只有一个OUT参数时,返回值类型应与该参数一致
create or replace function testf(a integer, out b integer)
returns integer as $$

-- 具有多个OUT参数时,返回值类型应为record型
create or replace function testf(a integer, out b integer, out c integer)
returns record as $$

注意点二:函数的调用,显然这个传参方式比存储过程合理多了

select testf(5);
select * from testf(5);

 

三、执行方式

验证失败,第二句话存疑:

  • 函数可以像普通的 SQL 语句一样直接调用执行 √
  • 存储过程需要用 CALL 或 EXECUTE 语句来调用执行 ×
  • => 存储过程使用 CALL 语句来调用执行

不满足上述条件则会报错。没见过用 EXECUTE 语句来调用的例子。

四、事务处理

验证成功:

  • 函数无法控制事务
  • 存储过程能够控制事务:开启、提交或回滚事务

但是好像不需要用 begin; 开启事务了,因为本来就有一个 begin

1、存储过程

create procedure test()
as $$
    begin
        update score set grade=0;
		rollback;
        commit;
    end;
$$
language plpgsql;

2、函数

create function testf()
returns void as $$
    begin
        update score set grade=0;
		-- rollback;
        commit;
    end;
$$
language plpgsql;

不管是执行 rollback 还是 commit,都会出现报错,以下是 commit 的报错信息:

ERROR: 错误: 无效交易终止
CONTEXT: 在COMMIT的第4行的PL/pgSQL函数testf()

五、数据库兼容性

待验证:

  • 函数在不同的数据库系统之间具有更好的兼容性
  • 存储过程在不同的数据库系统之间可能存在差异

 

 

你可能感兴趣的:(数据库原理与实践,数据库,sql,学习)