介绍

  PL/pgSQL 是PostgreSQL 数据库系统的一个可加载的过程语言。 PL/pgSQL 的设计目标是创建一种可加载的过程语言,可以 用于创建函数和触发器过程, 为SQL 语言增加控制结构, 执行复杂的计算 继承所有用户定义类型、函数、操作符, 定义为被服务器信任的语言。PL/pgSQL创建的函数可以在那些使用内置函数一样的情形下使用。 比如,可以创建复杂的条件计算函数,并随后将之用于定义操作符或者用于函数索引中。

使用PL/pgSQL的优点

  • SQL是PostgreSQL和大多数其它关系型数据库的命令语言。
  • 它是可移植的并且容易学习使用。但是所有SQL语句都必须由数据库服务器独立地执行.
  • 通过PL/pgSQL,可以把运算块和一系列命令在数据库服务器内部组成一个块, 这样就拥有了过程语言的能力并且简化 SQL 的使用, 因而节约了大量的时间,因为不需要进行客户端/服务器通讯。
  • 消除了服务器和客户端之间的往返通信。
  • 客户端不需要的中间结果无需在服务器端和客户端来回传递。
  • 不需要额外的语法分析步骤。比起不使用存储函数来,这样做能够产生明显的性能提升

块结构

  PL/pgSQL是一个块结构语言。函数定义的所有文本都必须是一个块。一个块用下面的方法定义:
  PL/pgSQL程序由三个部分组成,即声明部分、执行部分、异常处理部分。
  PL/pgSQL的结构如下:

DECLARE
--声明部分: 在此声明PL/SQL用到的变量,类型及游标.
BEGIN
-- 执行部分: 过程及SQL语句,即程序的主要部分
EXCEPTION
-- 执行异常部分: 错误处理
END;

其中:执行部分不能省略。

  • 块中的每一个declaration和每一条statement都由一个分号终止
  • 块支持嵌套,嵌套时子块的END后面必须跟一个分号,最外层的块END后可不跟分号
  • BEGIN后面不必也不能跟分号,END后跟的label名必须和块开始时的标签名一致
  • 所有关键字都不区分大小写。标识符被隐含地转换成小写字符,除非被双引号包围
  • 声明的变量在当前块及其子块中有效,子块开始前可声明并覆盖(只在子块内覆盖)外部块的同名变量
  • 变量被子块中声明的变量覆盖时,子块可以通过外部块的label访问外部块的变量

变量声明

声明一个变量的语法如下:

name [ CONSTANT ] type [ NOT NULL ] [ { DEFAULT | := } expression ];

这跟oracle中的存储过程声明变量是一样的。如

name text := 'lottu';
empno numeric := 110;

PL/pgSQL程序设计中的变量定义与SQL的标识符定义的要求相同。要求和限制有:

  • 标识符名不能超过30字符;
  • 第一个字符必须为字母;
  • 不分大小写;
  • 不能用’-‘(减号);
  • 不能是SQL保留字。

参数

声明一个参数的语法如下:

name [in|out|in out] type

如果只指定输入参数类型,不指定参数名,则函数体里一般用$1,$n这样的标识符来使用参数。

CREATE OR REPLACE FUNCTION discount(NUMERIC)
RETURNS NUMERIC
AS $$
BEGIN
RETURN $1 * 0.8;
END;
$$ LANGUAGE PLPGSQL;

但该方法可读性不好,此时可以为$n参数声明别名,然后可以在函数体内通过别名(ALIAS FOR)指向该参数值。

CREATE OR REPLACE FUNCTION discount(NUMERIC)
RETURNS NUMERIC
AS $$
DECLARE
total ALIAS FOR $1;
BEGIN
RETURN total * 0.8;
END;
$$ LANGUAGE PLPGSQL;

幸好PostgreSQL提供另外一种更为直接的方法来声明函数参数,即在声明参数类型时同时声明相应的参数名。

CREATE OR REPLACE FUNCTION discount(total NUMERIC)
RETURNS NUMERIC
AS $$
BEGIN
RETURN total * 0.8;
END;
$$ LANGUAGE PLPGSQL;

注释

在PL/SQL里,可以使用两种符号来写注释,即:

使用双 ‘-‘ ( 减号) 加注释PL/SQL允许用 – 来写注释,它的作用范围是只能在一行有效。如:
-- This is a single-line comments ...
使用 /* */ 来加一行或多行注释,如:
/*
This is a multiline comment ...
*/

案例分析

  采用跟oracle的plsql存储过程做对比。

--使用PL/PgSQL语言的函数定义如下:
CREATE FUNCTION somefunc() RETURNS integer AS $$
DECLARE
quantity integer := 30;
BEGIN
-- Prints 30
RAISE NOTICE 'Quantity here is %', quantity;
quantity := 50;
-- Create a subblock
DECLARE
quantity integer := 80;
BEGIN
-- Prints 80
RAISE NOTICE 'Quantity here is %', quantity;
END;
-- Prints 50
RAISE NOTICE 'Quantity here is %', quantity;
RETURN quantity;
END;
$$ LANGUAGE plpgsql;
-- 使用plsql语言编写如下:
DECLARE
quantity number := 30;
BEGIN
-- Prints 30
DBMS_OUTPUT.PUT_LINE('Quantity here is ' || quantity);
quantity := 50;
-- Create a subblock
DECLARE
quantity number := 80;
BEGIN
-- Prints 80
DBMS_OUTPUT.PUT_LINE('Quantity here is ' || quantity);
END;
-- Prints 50
DBMS_OUTPUT.PUT_LINE('Quantity here is ' || quantity);
END;

该案例而说;postgres存储过程跟oracle存储过程结构很相似。postgres中的'RAISE NOTICE'替换了oracle中'DBMS_OUTPUT.PUT_LINE'。

函数重载(Overwrite)

  在PostgreSQL中,多个函数可共用同一个函数名,但它们的参数必须得不同。这一规则与面向对象语言(比如Java)中的函数重载类似。也正因如此,在PostgreSQL删除函数时,必须指定其参数列表,如:

DROP FUNCTION get_array(anyelement, anyelement);

另外,在实际项目中,经常会用到CREATE OR REPLACE FUNCTION去替换已有的函数实现。如果同名函数已存在,但输入参数列表不同,会创建同名的函数,也即重载。如果同名函数已存在,且输入输出参数列表均相同,则替换。如果已有的函数输入参数列表相同,但输出参数列表不同,则会报错,并提示需要先DROP已有的函数定义。

PostgreSQL存储过程(2)-基于PL/PgSQL的存储过程的更多相关文章

  1. postgresql PL/pgSQL—存储过程结构和变量声明

    ref: https://www.postgresql.org/docs/9.6/static/plpgsql-structure.html 一. 函数结构 CREATE FUNCTION somef ...

  2. 用PL/pgSQL写postgreSQL的存储过程[转]

    http://blog.chinaunix.net/uid-7591044-id-1742967.html 今天学会了用 PL/pgSQL 写 postgreSQL 的存储过程,网上资料实在少得可怜, ...

  3. 基于oracle 的PL/SQL编程 - 存储过程

    接上篇,游标使用的语句,相当于一段匿名的函数,窗口关闭了就不存在了.如果想要窗口关闭了,还能继续执行那段代码,就需要存储过程了: PLSQL是指一个个PLSQL的业务处理过程存储起来进行复用,这些被存 ...

  4. oracle的存储过程和函数(PL/SQL)

    czmmiao 存储过程概述 存储过程是子程序的一种类型,能够完成一些任务,作为schema对象存储于数据库.是一个有名字的PL/SQL代码块,支持接收或不接受参数,同时也支持参数输出.一个存储过程通 ...

  5. PL/SQL之--存储过程

    一.存储过程 存储过程是一组为了完成特定功能的SQL 语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它.oracle可以把PL/SQL程序储存在数 ...

  6. 基于Jquery+Ajax+Json+存储过程 高效分页

    在做后台开发中,都会有大量的列表展示,下面给大家给大家分享一套基于Jquery+Ajax+Json+存储过程高效分页列表,只需要传递几个参数即可.当然代码也有改进的地方,如果大家有更好的方法,愿留下宝 ...

  7. PL/SQL之存储过程和函数

    1.创建存储过程 .1语法: CREATE[OR REPLACE] PROCEDURE [schema.] procedure_name[(argument[{IN|OUT|IN OUT}] data ...

  8. 使用PL/SQL编写存储过程访问数据库

    一.实验目的 熟悉使用存储过程来进行数据库应用程序的设计. 二.实验内容 对学生-课程数据库,编写存储过程,完成下面功能: 1.统计离散数学的成绩分布情况,即按照各分数段统计人数: 2.统计任意一门课 ...

  9. Mybatis之基于XML的调用存储过程与手动回滚事务

    一.调用存储过程 一.返回单个值 1.存储过程准备 这里先创建一个存储过程,传入参数为age,传出参数为count.然后先测试一下是否正确. CREATE DEFINER=`root`@`localh ...

随机推荐

  1. Flutter 1.0 正式版: Google 的便携 UI 工具包

    Flutter 1.0 正式版: Google 的便携 UI 工具包 文 / Tim Sneath,Google Dart & Flutter 产品组产品经理 Flutter 是 Google ...

  2. 《开发专家 Visual C 开发入行真功夫》笔记

    智能感知的功能,输入 is 后,同时按下Alt + →这两个键就出现了供选择变量.方法.宏等的列表,继续输入 in 后,isInit就出来了. stdafx.h预编译头文件,.h应用程序主头文件,do ...

  3. grub的boot loader安装在磁盘上的位置

    在很多资料上介绍grub的引导过程时,都是:bios->MBR->boot loaderboot loader是grub或者lilo.但是他是放在什么位置?很多资料上都没有标明. 通过阅读 ...

  4. 接口、抽象类、泛型、hashMap

    看到hashMap的put方法的第一行代码就懵逼了 就不继续往下看了 用简单的代码还原第一行代码 TsInter.java 接口 为什么要使用接口,比如写文章一样,我先列个大纲 //interface ...

  5. MySQL 数据库 varchar 到底可以存多少个汉字,多少个英文呢?我们来搞搞清楚

    一.关于UTF-8 UTF-8 Unicode Transformation Format-8bit.是用以解决国际上字符的一种多字节编码. 它对英文使用8位(即一个字节) ,中文使用24位(三个字节 ...

  6. HtmlUnitDriver 网页内容动态抓取

    #抓取内容 WebDriver driver = new HtmlUnitDriver(false); driver.get(url); String html = driver.getPageSou ...

  7. Oracle两个数据库互相访问,DBLink使用-转

    测试条件:假设某公司总部在北京,新疆有其下属的一个分公司.在本次测试中,新疆的计算机为本地计算机,即本要的IP地址为:192.168.1.100 北京的总部有一个集中的数据库,其SID是SIDBJ,用 ...

  8. unity-------Light的各个参数使用

    网上看到一篇关于灯光的文章,描述的很详细,如下: Lights will bring personality and flavor to your game. You use lights to il ...

  9. eclipse debug 执行到断点处并没有停下,断点无效问题

    转自:http://blog.csdn.net/cuidiwhere/article/details/14434439 现象: 利用eclipse debug时,执行到断点处并没有停下.正常情况下,在 ...

  10. C#中按模板操作Word —— 如何向Word中插入图片

    一.Word对象模型的重叠性分析 本文主要介绍通过书签Bookmark向Word文档中插入图片的方法.在此之前我们先简单讨论下Word对象模型的重叠性.如果你对Word对象模型还不熟悉,请参考本专栏第 ...