PostgreSQL | FunctionProcedure | 函数与存储过程的区别

文章目录

  • PostgreSQL | Function&Procedure | 函数与存储过程的区别
    • 1. 简述
      • 书面说法
      • 大白话讲
    • 2. 函数(Function)
      • 2.1 定义
      • 2.2 用途
      • 2.3 执行
      • 2.4 事务处理
      • 2.5 说点例子
        • 1. 当参数都是IN类时
        • 2. 参数中出现OUT、INOUT参数时
    • 3. 存储过程(Procedure)
      • 3.1 定义
      • 3.2 用途
      • 3.3 执行
      • 3.4 事务处理
      • 3.5 说点例子
    • 问题
    • 参阅

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 ] FUNCTIONname ( [ [ 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
BEGINreturn 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
    BEGINb := a+b;return b;
    END;
    $$;
    

    在这里插入图片描述

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

    --ERROR:  function result type must be integer because of OUT parametersCREATE OR REPLACE FUNCTION f01(IN a INT,INOUT b INT) RETURNS VARCHARLANGUAGE plpgsqlAS $$DECLAREBEGINb := 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
    BEGINb := 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
    BEGINb := 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
    BEGINb := 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 ] PROCEDUREname ( [ [ 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
    BEGINb := 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
    BEGINb := a+b;c := b*b;
    END;
    $$;
    

问题

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

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

    CREATE OR REPLACE FUNCTION f01() RETURNS VOID Language plpgsql
    AS $$
    DECLARE
    BEGINCREATE TABLE IF NOT EXISTS t1(id int);DROP TABLE t1;
    END;
    $$;
    select f01();CREATE OR REPLACE PROCEDURE p01() Language plpgsql
    AS $$
    DECLARE
    BEGINCREATE 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/579434.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一图梳理多模态领域发展简史

本文采用关系图的方式整理了:CLiP、ViLT、FLiP、ALBEF、CoCa、BLiP、VLMo、BEiT 和BEiT v3等近几年来经典的多模态大模型,以及这些工作的相互依托关系。灵感来自:跟李沐读论文系列——多模态串讲 1 模型关系图: ’ 2 各模型的架…

OpenAPI,已支持表单数据格式校验

OpenAPI 路径 开放平台 功能简介 「OpenAPI」- 支持表单数据格式校验。 通过「OpenAPI-新增表单数据」接口,新增数据时,若数据格式不匹配,会导致无法新增。 例如,数字不能新增到日期格式的表单字段。 请参考数据格式传参&a…

跨境电商测评攻略及其工具海外云手机的介绍

近些年随着跨境电商的火热,各商家纷纷想尽办法在激烈的竞争中取得一席之地,产品测评就是其中一个重要手段。本文将详细阐述跨境电商的测评攻略以及介绍一个测评的好工具海外云手机。 不管是速卖通,还是亚马逊、ebay,做测评都是非常…

软件测试的人是专门为难开发人员的吗?不不不我是来和开发抬杠的

我觉得就对对对,就不应该有测试这个岗位。 开发完,直接上线。 你看: 1.省了测试人员的薪酬,岗位。 2.省了测试时间,快速交付。快速上线,抢占市场。 3.让用户当免费的测试劳动力。有问题让客户提BUG就好…

Python (十六) pandas(四)

程序员的公众号:源1024,获取更多资料,无加密无套路! 最近整理了一波电子书籍资料,包含《Effective Java中文版 第2版》《深入JAVA虚拟机》,《重构改善既有代码设计》,《MySQL高性能-第3版》&…

<script setup> 的作用

一、使用<script setup> 之后&#xff0c;就不需要手动写以下代码&#xff0c;只要写逻辑代码 未加setup&#xff0c;vite 工程要加上下面代码 *export default{ * setup(){ * //只要写逻辑代码 * return{***} * } * } 加了setup &#xff0c;export default 、…

Java小案例-Feign的超时时间如何设置

前言 Feign的超时时间如何设置&#xff1f; Feign的超时时间设置方式并不固定&#xff0c;它取决于Feign在项目中是如何使用的&#xff0c;不同的使用方式&#xff0c;超时时间设置方式也不大相同&#xff0c;甚至还可能有坑。 由于文章会涉及到Feign的底层知识&#xff0c;…

【easy-ES使用】1.基础操作:增删改查、批量操作、分词查询、聚合处理。

easy-es、elasticsearch、分词器 与springboot 结合的代码我这里就不放了&#xff0c;我这里直接是使用代码。 基础准备&#xff1a; 创建实体类&#xff1a; Data // 索引名 IndexName("test_jc") public class TestJcES {// id注解IndexId(type IdType.CUSTOMI…

SpringBoot整合JWT+Spring Security+Redis实现登录拦截(一)登录认证

一、JWT简介 JWT 全称 JSON Web Token&#xff0c;JWT 主要用于用户登录鉴权&#xff0c;当用户登录之后&#xff0c;返回给前端一个Token&#xff0c;之后用户利用Token进行信息交互。 除了JWT认证之外&#xff0c;比较传统的还有Session认证&#xff0c;如何选择可以查看之前…

Spring中常见的BeanFactory后处理器

常见的BeanFacatory后处理器 先给出没有添加任何BeanFactory后处理器的测试代码 public class TestBeanFactoryPostProcessor {public static void main(String[] args) {GenericApplicationContext context new GenericApplicationContext();context.registerBean("co…

JAVA复习三——CH5 Java Collection 、CH6 MultiThread

CH5 Java Collection(集合) 5.1 Java集合框架&#xff08;位于java.util包中&#xff09; 图一 集合框架图 从上面的集合框架图可以看到&#xff0c;Java 集合框架主要包括两种类型的容器&#xff0c;一种是集合&#xff08;Collection&#xff09;&#xff0c;存储一个元素集…

信息犯罪与计算机取证

1.信息安全 信息安全的三种定义p2 ISO的 为数据处理系统建立和采取的技术和管理的安全保护&#xff0c;保护计算机硬件&#xff0c;软件数据不因偶尔或恶意的原因而受到破坏&#xff0c;更改和泄露 欧盟的 在既定的密级条件下&#xff0c;网络与信息系统抵御意外或恶意行为的能…

【C++】const 关键字

想要正确理解const关键字&#xff0c;只需记住一句话&#xff1a; cosnt关键字优先修饰左边&#xff0c;如果左边每东西&#xff0c;就作用于右边。 const int a; 修饰int a 不能改变 const int *a ; int const *a; 修饰int 指针a指向的地址可以改变&#xff0c;但是地址中…

flask文件夹列表改进版--Bug追踪

把当前文件夹下的所有文件夹和文件列出来&#xff0c;允许点击返回上层目录&#xff0c;允许点击文件夹进入下级目录并显示此文件夹内容 允许点击文件进行下载 from flask import Flask, render_template, send_file, request, redirect, url_for import osapp Flask(__name_…

抖店只能做和营业执照对照的产品吗?开店基础教程,新手可收藏!

我是王路飞。 抖店的营业执照有多重要呢&#xff1f;关系到你店铺的类型、类目和产品。 尤其是适合新手做的个体店&#xff0c;不涉及对公账户&#xff0c;货款可以直接提现到你的私人银行卡里&#xff0c;保证金也只有企业店铺的一半。 &#xff08;只需要身份证就能开通的…

深入Apache Commons Config:管理和使用配置文件

第1章&#xff1a;引言 咱们都知道&#xff0c;在软件开发中&#xff0c;管理配置文件是一件既重要又让人头疼的事。想象一下&#xff0c;咱们的应用程序有一堆设置需要调整&#xff0c;比如数据库的连接信息、应用的端口号&#xff0c;或者是一些功能的开关。如果这些信息硬编…

uni-app 命令行创建

1. 首先创建项目&#xff0c;命令如下: npx degit dcloudio/uni-preset-vue#vite-ts uni-app-demo如果出现报错&#xff0c;如下图. 大概率就是没有目录C:\Users\Administrator\AppData\Roaming\npm 解决办法&#xff1a; 创建目录 C:\Users\Administrator\AppData\Roaming\n…

基于nodemailer实现邮件发送、附件发送、多人发送

文章目录 1、QQ邮箱如何设置授权码2、具体代码 1、QQ邮箱如何设置授权码 QQ邮箱SMTP/IMAP服务 1、点击账号与安全 2、安全设置 3、设备管理&#xff0c;可以查看有多少个授权码 2、具体代码 from 这个参数&#xff0c;有两种写法 qq号qq.com"姓名"<qq号qq.co…

UDP Ping程序实现--第5关:客户端向服务器发送消息并接收消息

✨创作不易&#xff0c;还希望各位大佬支持一下 &#x1f44d; 点赞&#xff0c;你的认可是我创作的动力&#xff01; ⭐️ 收藏&#xff0c;你的青睐是我努力的方向&#xff01; ✏️ 评论&#xff0c;你的意见是我进步的财富&#xff01; 任务描述 本关任务&#xff1a;P…

【数据库系统概论】第3章-关系数据库标准语言SQL(2)

文章目录 3.4 数据查询3.4.1 单表查询3.4.2 连接查询3.4.3嵌套查询3.4.4 集合查询3.4.5 基于派生表的查询3.4.6 select 语句的目标列 3.4 数据查询 格式 SQL执行顺序 3.4.1 单表查询 基础查询 select * from student // 不重复 select distinct sname from student // 命名…