PostgreSQL | Function&Procedure | 函数与存储过程的区别

PostgreSQL | Function&Procedure | 函数与存储过程的区别

你可能想了解:PostgreSQL的Function和Procedure是一个东西吗?有什么区别?分别用于什么场景?如何更好的理解与记忆?有没有什么注意事项?

1. 简述

书面说法

函数(Function)和存储过程(Stored Procedure)都是数据库中的可重用代码块,用于执行特定的任务。

  1. 两者都提供了代码封装的机制,可以将一系列操作组织成单个单元。
  2. 都可以接受参数,并且可以返回结果。
  3. 存储过程和函数都可以在多个地方重复使用,减少了代码的冗余。
  4. 存储过程更倾向于执行一系列的操作,而函数更专注于返回一个值。

大白话讲

  1. Function通过Returns进行结果值返回,Procedure没有Returns返回值功能。(区别只是有没有Returns并不是说谁不能返回)
  2. Function通过Returns返回一个/组值,也可以returns record返回INOUT, OUT类参数值,这时候就不可以添加sql_body中的return语句。
  3. Procedure虽然不能使用Returns返回信息,但是可以通过INOUT类型参数返回多值,但不能使用Out。
  4. Functions可以被其它查询函数夹带调用并返回结果值(select XXX),Procedures不行,它只能使用CALL调用。
  5. 但是,我们说但是,在PG里Function和Procedure可以广义的理解差不多就是一个东西,结论看最后的问题示例。

2. 函数(Function)

2.1 定义

函数是一段预编译的代码,接受输入参数并返回一个值。函数可以是内置的系统函数,也可以是用户自定义的函数。

2.2 用途

函数主要用于计算和返回一个值,而不是执行一系列的SQL语句。它可以在SELECT语句、WHERE子句、ORDER BY子句等中使用。

2.3 执行

函数通常在SQL语句中嵌套使用,可以用于计算列值、过滤数据等。

2.4 事务处理

一般情况下,函数不包含事务控制语句,因为它们的目标是计算而不是执行修改数据库结构的操作。

2.5 说点例子

CREATE [ OR REPLACE ] FUNCTION
    name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )
    [ RETURNS rettype
      | RETURNS TABLE ( column_name column_type [, ...] ) ]
  { LANGUAGE lang_name
    | TRANSFORM { FOR TYPE type_name } [, ... ]
    | WINDOW
    | { IMMUTABLE | STABLE | VOLATILE }
    | [ NOT ] LEAKPROOF
    | { CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT }
    | { [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER }
    | PARALLEL { UNSAFE | RESTRICTED | SAFE }
    | COST execution_cost
    | ROWS result_rows
    | SUPPORT support_function
    | SET configuration_parameter { TO value | = value | FROM CURRENT }
    | AS 'definition'
    | AS 'obj_file', 'link_symbol'
    | sql_body
  } ...


-- 简单点,常用结构
CREATE OR REPLACE FUNCTION FUNCTION_NAME(IN PARA1 INT,INOUT PARA2 INT, OUT PARA3) 
RETURNS [TYPE|RECORD] LANGUAGE plpgsql
AS $$
DECLARE
BEGIN
[RETURN TYPE]
END;
$$;
1. 当参数都是IN类时

argmode:IN、INOUT、OUT(其中IN类参数类型可以将IN省略不写)

RETURNS TYPE + return xxx 按标准方式处理即可

CREATE OR REPLACE FUNCTION f01(IN a INT,IN b INT) RETURNS INT
LANGUAGE plpgsql
AS $$
DECLARE
BEGIN
	return a+b;
END;
$$;

select f01(1,2);

在这里插入图片描述

2. 参数中出现OUT、INOUT参数时

FUNCTION的sql_body中不能出现return行,否则报错;

  1. 若OUT、INOUT参数出现数量为1个,RETURNS Type 的TYPE需要与INOUT参数一致,且存储过程内不需要写return;
  • 正确写法

    CREATE OR REPLACE FUNCTION f01(IN a INT,INOUT b INT) RETURNS INT
    LANGUAGE plpgsql
    AS $$
    DECLARE
    BEGIN
    b := a+b;
    -- return b;
    END;
    $$;
    
    select f01(2,3);
    

  • 有INOUT、OUT,function内有return会报错

    --ERROR:  RETURN cannot have a parameter in function with OUT parameters
    CREATE OR REPLACE FUNCTION f01(IN a INT,INOUT b INT) RETURNS INT
    LANGUAGE plpgsql
    AS $$
    DECLARE
    BEGIN
      b := a+b;
      return b;
    END;
    $$;
    

    在这里插入图片描述

  • 有INOUT、OUT,RETURNS TYPE不匹配会报错

    --ERROR:  function result type must be integer because of OUT parameters
     CREATE OR REPLACE FUNCTION f01(IN a INT,INOUT b INT) RETURNS VARCHAR
     LANGUAGE plpgsql
     AS $$
     DECLARE
     BEGIN
       b := a+b;
     END;
     $$;
    

  • 有OUT参数时,调用时OUT参数位不需要输入信息的,否则报错-

    -- HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
    CREATE OR REPLACE FUNCTION f01(IN a INT,OUT b INT) RETURNS INT
    LANGUAGE plpgsql
    AS $$
    DECLARE
    BEGIN
      b := a+b;
    END;
    $$;
    
    select f01(2,3);
    

  • 有INOUT参数时,INOUT参数位必须输入信息,否则报错

    -- HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
    CREATE OR REPLACE FUNCTION f01(IN a INT,INOUT b INT) RETURNS INT
    LANGUAGE plpgsql
    AS $$
    DECLARE
    BEGIN
    b := a+b;
    END;
    $$;
    
    select f01(2);
    

  1. 若OUT、INOUT参数出现数量为多个,需要改写为RETURNS record
  • 正确写法

    CREATE OR REPLACE FUNCTION f01(IN a INT,INOUT b INT,OUT c INT) RETURNS record
    LANGUAGE plpgsql
    AS $$
    DECLARE
    BEGIN
      b := a+b;
      c := b*b;
    END;
    $$;
    
    select f01(1,2);
    

  • 未调整为RETURNS record,将会报错

    --ERROR: function result type must be record because of OUT parameters
    CREATE OR REPLACE FUNCTION f01(IN a INT,INOUT b INT,OUT c INT) RETURNS INT
    LANGUAGE plpgsql
    AS $$
    DECLARE
    BEGIN
     b := a+b;
     c := b*b;
    END;
    $$;
    

  • 多INOUT、OUT参数其它错误与1个INOUT、OUT基本一致,不再举例。

3. 存储过程(Procedure)

3.1 定义

存储过程是一组预编译的SQL语句集,被保存在数据库中,可以在需要时调用执行。存储过程通常由数据库管理员或有特殊权限的用户创建。

3.2 用途

存储过程主要用于封装和执行一系列的SQL语句,以完成特定的任务。它可以接受参数,并可以包含条件逻辑、循环等程序控制结构。

3.3 执行

存储过程可以被应用程序或其他存储过程调用。一旦创建,它们可以在数据库中被重复使用,提高了代码的可维护性和可重用性。

3.4 事务处理

存储过程可以包含事务控制语句,允许进行复杂的事务处理。

3.5 说点例子

CREATE [ OR REPLACE ] PROCEDURE
    name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )
  { LANGUAGE lang_name
    | TRANSFORM { FOR TYPE type_name } [, ... ]
    | [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
    | SET configuration_parameter { TO value | = value | FROM CURRENT }
    | AS 'definition'
    | AS 'obj_file', 'link_symbol'
    | sql_body
  } ...


-- 简单点,常用结构
CREATE OR REPLACE PROCEDURE PROCEDURE_NAME(IN/INOUT PARA1,...)
AS $$
Declare
BEGIN
END;
$$ Language plpgsql;
  1. 基本用法与Function一致,只是Procedure参数中不能使用OUT类型,且不能使用Returns返回数据。

    CREATE OR REPLACE PROCEDURE p01(IN a INT, INOUT b INT, INOUT c INT) Language plpgsql
    AS $$
    DECLARE
    BEGIN
      b := a+b;
      c := b*b;
    END;
    $$;
    
    call p01(2,3,4);
    

  2. 如果使用OUT参数将报错

    --ERROR:  procedures cannot have OUT arguments
    --HINT:  INOUT arguments are permitted.
    CREATE OR REPLACE PROCEDURE p01(IN a INT, INOUT b INT, OUT c INT) Language plpgsql
    AS $$
    DECLARE
    BEGIN
      b := a+b;
      c := b*b;
    END;
    $$;
    

问题

  1. 函数和存储过程是否都可以执行DDL?

    答案是:在PG中都可以执行,不过函数一般用来计算结果,最好不要夹带DDL语句;

    CREATE OR REPLACE FUNCTION f01() RETURNS VOID Language plpgsql
    AS $$
    DECLARE
    BEGIN
      CREATE TABLE IF NOT EXISTS t1(id int);
      DROP TABLE t1;
    END;
    $$;
    select f01();
    
    CREATE OR REPLACE PROCEDURE p01() Language plpgsql
    AS $$
    DECLARE
    BEGIN
    	CREATE TABLE IF NOT EXISTS t1(id int);
      DROP TABLE t1;
    END;
    $$;
    call p01();
    

  2. 为什么说PG中 函数 与 存储过程 广义上可以理解为一个东西?

    我们来看一个报错,通过报错提示我们发现,函数与存储过程在报错中都被叫做function

    CREATE OR REPLACE FUNCTION f01() RETURNS VOID Language plpgsql
    AS $$
    DECLARE
    BEGIN
    	-- 不存在这张表,会报错;
      DROP TABLE t123;
    END;
    $$;
    select f01();
    
    CREATE OR REPLACE PROCEDURE p01() Language plpgsql
    AS $$
    DECLARE
    BEGIN
    	-- 不存在这张表,会报错;
      DROP TABLE t456;
    END;
    $$;
    call p01();
    

参阅

SQL - CREATE FUNCTION
SQL - CREATE PROCEDURE
Procedures Vs. Functions in PostgreSQL





🎉如果对你有所帮助,可以点赞、关注、收藏起来,不然下次就找不到了🎉


【点赞】⭐️⭐️⭐️⭐️⭐️
【关注】⭐️⭐️⭐️⭐️⭐️
【收藏】⭐️⭐️⭐️⭐️⭐️

Thanks for watching.
Kenny

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2023-12-31 01:40:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-31 01:40:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-31 01:40:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-31 01:40:01       20 阅读

热门阅读

  1. Modbus4j核心代码讲解

    2023-12-31 01:40:01       42 阅读
  2. honoka的键盘#洛谷

    2023-12-31 01:40:01       37 阅读
  3. 【STL】std::map使用小结

    2023-12-31 01:40:01       34 阅读
  4. TypeScript 类方法装饰器

    2023-12-31 01:40:01       35 阅读
  5. 什么是redis雪崩

    2023-12-31 01:40:01       33 阅读
  6. ELF Strip

    2023-12-31 01:40:01       27 阅读
  7. RabbitMQ消息队列常见面试题

    2023-12-31 01:40:01       36 阅读
  8. Git 命令

    2023-12-31 01:40:01       28 阅读
  9. 【Linux】修复 Linux 错误 - 地址已在使用中

    2023-12-31 01:40:01       31 阅读
  10. ❀My排序算法学习之选择排序❀

    2023-12-31 01:40:01       34 阅读
  11. CAPL解析DBC文件

    2023-12-31 01:40:01       51 阅读
  12. OpenFeign相关面试题及答案

    2023-12-31 01:40:01       27 阅读
  13. linux安装nginx

    2023-12-31 01:40:01       27 阅读