iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >PostgreSQL存储过程源码分析
  • 366
分享到

PostgreSQL存储过程源码分析

2023-07-05 14:07:07 366人浏览 安东尼
摘要

这篇文章主要介绍了postgresql存储过程源码分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Postgresql存储过程源码分析文章都会有所收获,下面我们一起来看看吧。游标PL/pgSQL 游标允许我们

这篇文章主要介绍了postgresql存储过程源码分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Postgresql存储过程源码分析文章都会有所收获,下面我们一起来看看吧。

游标

PL/pgSQL 游标允许我们封装一个查询,然后每次处理结果集中的一条记录。游标可以将大结果集拆分成许多小的记录,避免内存溢出;另外,我们可以定义一个返回游标引用的函数,然后调用程序可以基于这个引用处理返回的结果集。

使用游标的步骤大体如下:

  • 声明游标变量;

  • 打开游标;

  • 从游标中获取结果;

  • 判断是否存在更多结果。如果存在,执行第 3 步;否则,执行第 5 步;

  • 关闭游标。

我们直接通过一个示例演示使用游标的过程:

DO $$DECLARE   rec_emp RECORD;  cur_emp CURSOR(p_deptid INTEGER) FOR    SELECT first_name, last_name, hire_date     FROM employees    WHERE department_id = p_deptid;BEGIN  -- 打开游标  OPEN cur_emp(60);  LOOP    -- 获取游标中的记录    FETCH cur_emp INTO rec_emp;    -- 没有找到更多数据时退出循环    EXIT WHEN NOT FOUND;    RaiSE NOTICE '%,% hired at:%' , rec_emp.first_name, rec_emp.last_name, rec_emp.hire_date;  END LOOP;  -- Close the cursor  CLOSE cur_emp;END $$;NOTICE:  Alexander,Hunold hired at:2006-01-03NOTICE:  Bruce,Ernst hired at:2007-05-21NOTICE:  David,Austin hired at:2005-06-25NOTICE:  Valli,Pataballa hired at:2006-02-05NOTICE:  Diana,Lorentz hired at:2007-02-07

首先,声明了一个游标 cur_emp,并且绑定了一个查询语句,通过一个参数 p_deptid 获取指定部门的员工;然后使用 OPEN 打开游标;接着在循环中使用 FETCH 语句获取游标中的记录,如果没有找到更多数据退出循环语句;变量 rec_emp 用于存储游标中的记录;最后使用 CLOSE 语句关闭游标,释放资源。

游标是 PL/pgSQL 中的一个强大的数据处理功能,更多的使用方法可以参考官方文档。

错误处理

报告错误和信息

PL/pgSQL 提供了 RAISE 语句,用于打印消息或者抛出错误:

RAISE level fORMat;

不同的 level 代表了错误的不同严重级别,包括:

DEBUG
LOG
NOTICE
INFO
WARNING
EXCEPTioN

在上文示例中,我们经常使用 NOTICE 输出一些信息。如果不指定 level,默认为 EXCEPTION,将会抛出异常并且终止代码运行。

format 是一个用于提供信息内容的字符串,可以使用百分号(%)占位符接收参数的值, 两个连写的百分号(%%)表示输出百分号自身。

以下是一些 RAISE 示例:

DO $$ BEGIN   RAISE DEBUG 'This is a debug text.';  RAISE INFO 'This is an information.';  RAISE LOG 'This is a log.';  RAISE WARNING 'This is a warning at %', now();  RAISE NOTICE 'This is a notice %%';END $$;INFO:  This is an information.WARNING:  This is a warning at 2020-05-16 11:27:06.138569+08NOTICE:  This is a notice %

从结果可以看出,并非所有的消息都会打印到客户端和服务器日志中。这个可以通过配置参数 client_min_messages 和 log_min_messages 进行设置。

对于 EXCEPTION 级别的错误,可以支持额外的选项:

RAISE [ EXCEPTION ] format USING option = expression [, ... ];RAISE [ EXCEPTION ] condition_name USING option = expression [, ... ];RAISE [ EXCEPTION ] SQLSTATE 'sqlstate' USING option = expression [, ... ];RAISE [ EXCEPTION ] USING option = expression [, ... ];

其中,option 可以是以下选项:

MESSAGE,设置错误消息。如果 RAISE 语句中已经包含了 format 字符串,不能再使用该选项。
DETAIL,指定错误详细信息。
HINT,设置一个提示信息。
ERRCODE,指定一个错误码(SQLSTATE)。可以是文档中的条件名称或者五个字符组成的 SQLSTATE 代码。
COLUMN、CONSTRAINT、DATATYPE、TABLE、SCHEMA,返回相关对象的名称。
以下是一些示例:

RAISE EXCEPTION 'Nonexistent ID --> %', user_id      USING HINT = 'Please check your user ID';RAISE 'Duplicate user ID: %', user_id USING ERRCODE = 'unique_violation';RAISE 'Duplicate user ID: %', user_id USING ERRCODE = '23505';RAISE division_by_zero;RAISE SQLSTATE '22012';

检查断言

PL/pgSQL 提供了 ASSERT 语句,用于调试存储过程和函数:

ASSERT condition [ , message ];

其中,condition 是一个布尔表达式;如果它的结果为真,ASSERT 通过;如果结果为假或者 NULL,将会抛出 ASSERT_FAILURE 异常。message 用于提供额外的错误信息,默认为“assertion failed”。例如:

DO $$ DECLARE   i integer := 1;BEGIN   ASSERT i = 0, 'i 的初始值应该为 0!';END $$;ERROR:  i 的初始值应该为 0!CONTEXT:  PL/pgSQL function inline_code_block line 5 at ASSERT

⚠️注意,ASSERT 只适用于代码调试;输出错误信息使用 RAISE 语句。

捕获异常

默认情况下,PL/pgSQL 遇到错误时会终止代码执行,同时撤销事务。我们也可以在代码块中使用 EXCEPTION 捕获错误并继续事务:

[ <<label>> ][ DECLARE    declarations ]BEGIN    statementsEXCEPTION    WHEN condition [ OR condition ... ] THEN        handler_statements    [ WHEN condition [ OR condition ... ] THEN          handler_statements      ... ]END;

如果代码执行出错,程序将会进入 EXCEPTION 模块;依次匹配 condition,找到第一个匹配的分支并执行相应的 handler_statements;如果没有找到任何匹配的分支,继续抛出错误。

以下是一个除零错误的示例:

DO $$ DECLARE   i integer := 1;BEGIN   i := i / 0;EXCEPTION  WHEN division_by_zero THEN    RAISE NOTICE '除零错误!';  WHEN OTHERS THEN    RAISE NOTICE '其他错误!';END $$;NOTICE:  除零错误!OTHERS 用于捕获未指定的错误类型。

PL/pgSQL 还提供了捕获详细错误信息的 GET STACKED DIAGNOSTICS 语句,具体可以参考官方文档。

自定义函数

要创建一个自定义的 PL/pgSQL 函数,可以使用 CREATE FUNCTION 语句:

CREATE [ OR REPLACE ] FUNCTION  name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )  RETURNS rettypeAS $$DECLARE  declarationsBEGIN  statements;  ...END; $$LANGUAGE plpgsql;

CREATE 表示创建函数,OR REPLACE 表示替换函数定义;name 是函数名;括号内是参数,多个参数使用逗号分隔;argmode 可以是 IN(输入)、OUT(输出)、INOUT(输入输出)或者 VARIADIC(数量可变),默认为 IN;argname 是参数名称;argtype 是参数的类型;default_expr 是参数的默认值;rettype 是返回数据的类型;AS 后面是函数的定义,和上文中的匿名块相同;最后,LANGUAGE 指定函数实现的语言,也可以是其他过程语言。

以下示例创建一个函数 get_emp_count,用于返回指定部门中的员工数量:

CREATE OR REPLACE FUNCTION get_emp_count(p_deptid integer) RETURNS integer AS $$DECLARE  ln_count integer;BEGIN  select count(*) into ln_count  from employees  where department_id = p_deptid;  return ln_count;END; $$LANGUAGE plpgsql;

创建该函数之后,可以像内置函数一样在 SQL 语句中进行调用:

select department_id,department_name,get_emp_count(department_id)from departments d;department_id|department_name     |get_emp_count|-------------|--------------------|-------------|           10|Administration      |            1|           20|Marketing           |            2|           30|Purchasing          |            6|...

PL/pgSQL 函数支持重载(Overloading),也就是相同的函数名具有不同的函数参数。例如,以下语句创建一个重载的函数 get_emp_count,返回指定部门指定日期之后入职的员工数量:

CREATE OR REPLACE FUNCTION get_emp_count(p_deptid integer, p_hiredate date) RETURNS integer AS $$DECLARE  ln_count integer;BEGIN  select count(*) into ln_count  from employees  where department_id = p_deptid and hire_date >= p_hiredate;  return ln_count;END; $$LANGUAGE plpgsql;

查询每个部门 2005 年之后入职的员工数量:

select department_id,department_name,get_emp_count(department_id),get_emp_count(department_id, '2005-01-01')from departments d;department_id|department_name     |get_emp_count|get_emp_count|-------------|--------------------|-------------|-------------|           10|Administration      |            1|            0|           20|Marketing           |            2|            1|           30|Purchasing          |            6|            4|...

我们再来看一个 VARIADIC 参数的示例:

CREATE OR REPLACE FUNCTION sum_num(  VARIADIC nums numeric[])  RETURNS numericAS $$DECLARE ln_total numeric;BEGIN  SELECT SUM(nums[i]) INTO ln_total  FROM generate_subscripts(nums, 1) t(i);  RETURN ln_total;END; $$LANGUAGE plpgsql;

参数 nums 是一个数组,可以传入任意多个参数;然后计算它们的和值。例如:

SELECT sum_num(1,2), sum_num(1,2,3);sum_num|sum_num|-------|-------|      3|      6|

如果函数不需要返回结果,可以返回 void 类型;或者直接使用存储过程。

存储过程

PostgreSQL 11 增加了存储过程,使用 CREATE PROCEDURE 语句创建:

CREATE [ OR REPLACE ] PROCEDURE  name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )AS $$DECLARE  declarationsBEGIN  statements;  ...END; $$LANGUAGE plpgsql;

存储过程的定义和函数主要的区别在于没有返回值,其他内容都类似。以下示例创建了一个存储过程 update_emp,用于修改员工的信息:

CREATE OR REPLACE PROCEDURE update_emp(  p_empid in integer,  p_salary in numeric,  p_phone in varchar)AS $$BEGIN  update employees   set salary = p_salary,      phone_number = p_phone  where employee_id = p_empid;END; $$LANGUAGE plpgsql;

调用存储过程使用 CALL 语句:

call update_emp(100, 25000, '515.123.4560');

事务管理

在存储过程内部,可以使用 COMMIT 或者 ROLLBACK 语句提交或者回滚事务。例如:

create table test(a int);CREATE PROCEDURE transaction_test()LANGUAGE plpgsqlAS $$BEGIN    FOR i IN 0..9 LOOP        INSERT INTO test (a) VALUES (i);        IF i % 2 = 0 THEN            COMMIT;        ELSE            ROLLBACK;        END IF;    END LOOP;END$$;CALL transaction_test();select * from test;a|-|0|2|4|6|8|

只有偶数才会被最终提交。

关于“PostgreSQL存储过程源码分析”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“PostgreSQL存储过程源码分析”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网精选频道。

--结束END--

本文标题: PostgreSQL存储过程源码分析

本文链接: https://www.lsjlt.com/news/352124.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • PostgreSQL存储过程源码分析
    这篇文章主要介绍了PostgreSQL存储过程源码分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇PostgreSQL存储过程源码分析文章都会有所收获,下面我们一起来看看吧。游标PL/pgSQL 游标允许我们...
    99+
    2023-07-05
  • Oracle存储过程Procedure分析
    本篇内容介绍了“Oracle存储过程Procedure分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!我...
    99+
    2024-04-02
  • MySQL的存储函数与存储过程实例代码分析
    这篇文章主要介绍了MySQL的存储函数与存储过程实例代码分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇MySQL的存储函数与存储过程实例代码分析文章都会有所收获,下面我们一...
    99+
    2023-03-06
    mysql
  • mysql存储过程举例分析
    这篇文章主要讲解了“mysql存储过程举例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“mysql存储过程举例分析”吧!(1).格式MySQL存储过程创...
    99+
    2024-04-02
  • PostgreSQL中支持存储过程吗
    是的,PostgreSQL支持存储过程。存储过程是一组预先编译的SQL语句,可以在数据库中进行重复性操作。通过存储过程,用户可以将常...
    99+
    2024-04-09
    PostgreSQL
  • mysql存储过程与存储函数实例分析
    这篇文章主要介绍了mysql存储过程与存储函数实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇mysql存储过程与存储函数实例分析文章都会有所收获,下面我们一起来看看吧。...
    99+
    2022-11-30
    mysql
  • MySQL的存储过程实例分析
    今天小编给大家分享一下MySQL的存储过程实例分析的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一...
    99+
    2024-04-02
  • oracle PL/SQL与存储过程分析
    本篇内容介绍了“oracle PL/SQL与存储过程分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!PL...
    99+
    2024-04-02
  • mysql存储过程的案例分析
    这篇文章主要介绍mysql存储过程的案例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1、什么是存储过程为以后的使用而保存的一条或多条MySQL语句的集合。存储过程思想上就是数据...
    99+
    2024-04-02
  • Sql Server存储过程实例分析
    今天小编给大家分享一下Sql Server存储过程实例分析的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。从存储过程...
    99+
    2023-06-30
  • PostgreSQL中的存储过程是什么
    存储过程是一组预编译的SQL语句和逻辑操作,通过一个命名的过程存储在数据库服务器中,用于执行特定的任务或操作。存储过程可以接受输入参...
    99+
    2024-04-09
    PostgreSQL
  • PostgreSQL中vacuum过程分析
    本篇内容主要讲解“PostgreSQL中vacuum过程分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PostgreSQL中vacuum过程分析”吧!一、数...
    99+
    2024-04-02
  • PostgreSQL MVCC源码的示例分析
    这篇文章主要为大家展示了“PostgreSQL MVCC源码的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“PostgreSQL MVCC源码的示例分析...
    99+
    2024-04-02
  • MySQL中存储过程和存储函数的示例分析
    这篇文章主要为大家展示了“MySQL中存储过程和存储函数的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“MySQL中存储过程和存储函数的示例分析”这篇文...
    99+
    2024-04-02
  • mysql中存储过程的示例分析
    这篇文章主要介绍了mysql中存储过程的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。在mysql中,存储过程是一组为了完成特定功能...
    99+
    2024-04-02
  • 分析Golang存储过程的优缺点
    Golang是一种由Google开发的开源编程语言,被广泛应用于后端开发。在Golang中,虽然没有像其他数据库相关语言那样直接支持存储过程,但通过调用数据库的原生SQL语句,可以实现...
    99+
    2024-02-26
    golang 存储过程 优势 劣势 sql语句
  • mysql存储过程用法实例分析
    本文实例讲述了mysql存储过程用法。分享给大家供大家参考,具体如下: 概述: 简单的说,就是一组SQL语句集,功能强大,可以实现一些比较复杂的逻辑功能,类似于JAVA语言中的方法; 存储过程跟触发器有点类...
    99+
    2024-04-02
  • Oracle存储过程中Procedure简单分析
    今天就跟大家聊聊有关Oracle存储过程中Procedure简单分析,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。 这...
    99+
    2024-04-02
  • ADO.NET存储过程调用举例分析
    这篇文章主要讲解了“ADO.NET存储过程调用举例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“ADO.NET存储过程调用举例分析”吧!此示例很简单,因为存储过程不需要任何输入参数。也就...
    99+
    2023-06-17
  • ConcurrentHashMap 存储结构源码解析
    目录引言1 ConcurrentHashMap 1.71.存储结构2. 初始化3. put4. 扩容 rehash5. get2 ConcurrentHashMap 1.81. 存储...
    99+
    2022-11-13
    ConcurrentHashMap 存储结构 ConcurrentHashMap 存储
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作