http://blog.chinaunix.net/uid-7591044-id-1742967.html

今天学会了用 PL/pgSQL 写 postgreSQL 的存储过程,网上资料实在少得可怜,唯一能搜到的一些还是抄来抄去的;还是翻postgresql的文档吧,把今天解决的问题说一下吧,希望对其他人有帮助。
问题是这样的,有一张message表:
CREATE TABLE message
(
id int8 NOT NULL,
receiveuserid int8,
senduserid int8,
receivedelete bool DEFAULT false,
senddelete bool DEFAULT false,
……
CONSTRAINT usermessage_pkey PRIMARY KEY (id)
)

去其他字段,senduserid是发信息的用户id,senddelete如为true则表示这条消息被发信人所删除;至于receive我就不用说
了。一条信息只有被发信人和收信人都删除,才能真正从表里删除(这是显然的,否则收信人删了一条消息后,发信人的“发件箱”里就会找不到这条消息)。
所以删除消息(可能是多条消息)的时候要进行各种判断(是否是发信人?是否是收信人?是否真正删除?),用单条SQL语句完成这个工作显然有些困难(当然用循环嵌套select不考虑效率的话也是可以实现的),只好写存储过程了。
顺便介绍常用的PL/pgSQL结构和语法吧:

  • 结构

    PL/pgSQL是一种块结构的语言,比较方便的是用pgAdmin III新建Function,填入一些参数就可以了。基本上是这样的:

    CREATE OR REPLACE FUNCTION 函数名(参数1,[整型 int4, 整型数组 _int4, …])
    RETURNS 返回值类型 AS
    $BODY$
    DECLARE
    变量声明
    BEGIN
    函数体
    END;
    $BODY$
    LANGUAGE ‘plpgsql’ VOLATILE;

  • 变量类型

    除了postgresql内置的变量类型外,常用的还有 RECORD ,表示一条记录。

  • 赋值

    赋值和Pascal有点像:“变量 := 表达式;”
    有些奇怪的是连接字符串的是“||”,比如 sql := ‘SELECT * FROM’ || table || ‘WHERE …’;

  • 判断

    判断又和VB有些像:
    IF 条件 THEN

    ELSEIF 条件 THEN

    ELSE

    END IF;

  • 循环

    循环有好几种写法:
    WHILE expression LOOP
    statements
    END LOOP;
    还有常用的一种是:(从1循环到9可以写成FOR i IN 1..9 LOOP)
    FOR name IN [ REVERSE ] expression .. expression LOOP
    statements
    END LOOP;

  • 其他

    还有几个常用的函数:
    SELECT INTO record …; 表示将select的结果赋给record变量(RECORD类型)
    PERFORM query; 表示执行query并丢弃结果
    EXECUTE sql; 表示执行sql语句,这条可以动态执行sql语句(特别是由参数传入构造sql语句的时候特别有用)

最后,贴出解决上面这个问题的存储过程吧:

     CREATE OR REPLACE FUNCTION message_deletes(ids "varchar", userid int8)
RETURNS int4 AS
$BODY$
DECLARE
r RECORD;
del bool;
num int4 := 0;
sql "varchar";
BEGIN
sql := 'select id,receiveuserid,senduserid,senddelete,receivedelete from message where id in (' || ids || ')';
FOR r IN EXECUTE sql LOOP
del := false;
IF r.receiveuserid=userid and r.senduserid=userid THEN
del := true;
ELSEIF r.receiveuserid=userid THEN
IF r.senddelete=false THEN
update message set receivedelete=true where id = r.id;
ELSE
del := true;
END IF;
ELSEIF r.senduserid=userid THEN
IF r.receivedelete=false THEN
update message set senddelete=true where id = r.id;
ELSE
del := true;
END IF;
END IF;
IF del THEN
delete from message where id = r.id;
num := num + 1;
END IF;
END LOOP;
return num;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
 

测试使用:

用PL/pgSQL写postgreSQL的存储过程[转]的更多相关文章

  1. PostgreSQL存储过程(2)-基于PL/PgSQL的存储过程

    介绍 PL/pgSQL 是PostgreSQL 数据库系统的一个可加载的过程语言. PL/pgSQL 的设计目标是创建一种可加载的过程语言,可以 用于创建函数和触发器过程, 为SQL 语言增加控制结构 ...

  2. PL/pgSQL学习笔记之三

    http://www.postgresql.org/docs/9.1/static/plpgsql-overview.html 39.1.2. Supported Argument and Resul ...

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

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

  4. PL/pgSQL学习笔记之七

    http://www.postgresql.org/docs/9.1/static/plpgsql-declarations.html 如果一个PL/pgSQL函数声明了输出参数,输出参数被赋予$n名 ...

  5. PostgreSQL函数(存储过程)----笔记

    PostgreSQL 函数也称为 PostgreSQL 存储过程. PostgreSQL 函数或存储过程是存储在数据库服务器上并可以使用SQL界面调用的一组SQL和过程语句(声明,分配,循环,控制流程 ...

  6. PL/pgSQL学习笔记之八

    http://www.postgresql.org/docs/9.1/static/plpgsql-declarations.html 另外一种声明 PL/pgSQL 函数的方法是使用 returns ...

  7. PL/pgSQL学习笔记之五

    http://www.postgresql.org/docs/9.1/static/plpgsql-declarations.html 39.3. 声明 块中使用的所有的变量必须在块的声明节中进行声明 ...

  8. PL/pgSQL学习笔记之四

    http://www.postgresql.org/docs/9.1/static/plpgsql-structure.html 39.2. PL/pgSQL 的结构 PL/pgSQL是一种块式结构的 ...

  9. PL/pgSQL学习笔记之二

    39.1.1 使用 PL/pgSQL的好处 SQL是 PostgreSQL和其他大多数关系型数据库作为查询语言而使用的语言.它可移植,并容易学习.但是SQL语句必须被数据库服务器逐条地执行. 这意味着 ...

随机推荐

  1. React-Native调用支付宝,微信

    https://www.pingxx.com/docs/downloads Ping++ 是为移动端应用以及 PC 网页量身打造的下一代支付系统,通过一个 SDK 便可以同时支持移动端以及 PC 端网 ...

  2. 解决WPF中重载Window.OnRender函数失效问题

    今天实验一个绘图算法的时候,偶然发现重载Window.OnRender的方法是没有效果的. public partial class MainWindow : Window { public Main ...

  3. hdu 2176 取石子游戏

    http://acm.hdu.edu.cn/showproblem.php?pid=2176 提示:尼姆博弈,异或 #include <iostream> #include <cst ...

  4. hihoCoder - 1082 - 然而沼跃鱼早就看穿了一切 (字符串处理!!)

    #1082 : 然而沼跃鱼早就看穿了一切 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描写叙述 fjxmlhx每天都在被沼跃鱼刷屏,因此他急切的找到了你希望你写一个程序屏蔽全 ...

  5. 根据url下载图片和页面

    需要将&tp=webp&wxfrom=5去掉,既可以在任何地方显示,也可以下载了 http://mmbiz.qpic.cn/mmbiz_jpg/bf8pC39RBhGFOH1ib9Ac ...

  6. 【spring cloud】spring cloud 使用feign调用,1.fallback熔断器不起作用,2.启动报错Caused by: java.lang.ClassNotFoundException: com.netflix.hystrix.contrib.javanica.aop.aspectj.Hystri解决

    示例GitHub源码地址:https://github.com/AngelSXD/springcloud 1.首先使用feign调用,需要配置熔断器 2.配置熔断器需要将熔断器注入Bean,熔断器类上 ...

  7. Confman - 针对「Node 应用」的配置文件加载模块

    一句话介绍 confman 是一个强大的配置文件加载器,无论你喜欢 yaml .cson.json.properties.plist.ini.toml.xml 还是 js,都能满足你的愿望,并且更加简 ...

  8. iOS开源项目:JSONKit

    一个Json解析库,其特点是代码简单,只有一个.h和.m文件. https://github.com/johnezang/JSONKit JSON(JavaScript Object Notation ...

  9. iOS:上线的基本流程

    1.创建唯一标书符App ID 首先打开开发者网站,进入证书页面,我们点击Identifiers下边App IDs选项,然后点击右上角加号,如图: 2.申请发布证书 我们点击Certificates下 ...

  10. 数学图形(1.19)Doppler spiral螺线

    一种左右对称的螺线 相关软件参见:数学图形可视化工具,使用自己定义语法的脚本代码生成数学图形.该软件免费开源.QQ交流群: 367752815 vertices = t = *PI) to (*PI) ...