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. Android中的数据存储(二):文件存储 2017-05-25 08:16 35人阅读 评论(0) 收藏

    文件存储 这是本人(菜鸟)学习android数据存储时接触的有关文件存储的知识以及本人自己写的简单地demo,为初学者学习和使用文件存储提供一些帮助.. 如果有需要查看SharedPreference ...

  2. mui 图片预览

    1. 图片放大滑动预览需要    mui.zoom.js   mui.previewimage.js 2. 调用  mui.previewImage(); 3. 滑动过程中禁止图片缩放  注释掉下面代 ...

  3. XmlnsDefinitionAttribute Is Pretty Nifty

    When we want to declaratively use our custom controls or reference the types we defined in XAML, we ...

  4. Linux使用jstat命令查看jvm的GC情况(转)

    B. jstack jstack主要用来查看某个Java进程内的线程堆栈信息.语法格式如下: 1 jstack [option] pid 2 jstack [option] executable co ...

  5. java中引用的原理

    转自:http://blog.163.com/xubin_3@126/blog/static/112987702200962211145825/ 在Java中的引用类型,是指除了基本的变量类型之外的所 ...

  6. Orchard运用 - 定制博客分页显示

    一般,对于条目过多的系统或博客,分页显示是最简单的方式.目前分页方式基本有三种格式: 1.显示所有信息,包括标明当前页面,提供上一页和下一页链接和使用首页和末页链接. 2.只标注上一页和下一页链接. ...

  7. Plugin with id 'com.github.dcendents.android-maven' not found

    导入开源项目的时候老是报这个错 Error:(2, 0) Plugin with id 'com.github.dcendents.android-maven' not found 挺郁闷的,不知道是 ...

  8. 使用jQuery通过点击它删除HTML表格行-超简单

    jQuery的已成为所有时刻的最常用和最喜爱的JavaScript框架之一.它不仅不会减少在JavaScript编码简单的技术开销,而且也使您的代码的跨浏览器兼容.我已经写了许多关于jQuery教程, ...

  9. [HNOI2002]营业额统计 Splay tree入门题

    题目连接:http://www.lydsy.com/JudgeOnline/problem.php?id=1588 1588: [HNOI2002]营业额统计 Time Limit: 5 Sec   ...

  10. 获取jQuery版本号

    今天在一个页面需要知道jquery版本号,来决定使用什么样的方法,有以下方式可以获取到 $.fn.jquery $.prototype.jquery 这两种方式都可以获取到jquery的版本号