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


    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语句的时候特别有用)

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

     1     CREATE OR REPLACE FUNCTION message_deletes(ids "varchar", userid int8)
     2       RETURNS int4 AS
     3     $BODY$
     4     DECLARE
     5       r RECORD;
     6       del bool;
     7       num int4 := 0;
     8       sql "varchar";
     9     BEGIN
    10       sql := 'select id,receiveuserid,senduserid,senddelete,receivedelete from message where id in (' || ids || ')';
    11       FOR r IN EXECUTE sql LOOP
    12         del := false;
    13         IF r.receiveuserid=userid and r.senduserid=userid THEN
    14           del := true;
    15         ELSEIF r.receiveuserid=userid THEN
    16           IF r.senddelete=false THEN
    17             update message set receivedelete=true where id = r.id;
    18           ELSE
    19             del := true;
    20           END IF;
    21         ELSEIF r.senduserid=userid THEN
    22           IF r.receivedelete=false THEN
    23             update message set senddelete=true where id = r.id;
    24           ELSE
    25             del := true;
    26           END IF;
    27         END IF;
    28         IF del THEN
    29           delete from message where id = r.id;
    30           num := num + 1;
    31         END IF;
    32       END LOOP;
    33       return num;
    34     END;
    35     $BODY$
    36       LANGUAGE 'plpgsql' VOLATILE;
    View Code
     

    测试使用:
    postgres PL/pgSQL

  • 相关阅读:
    395. Coins in a Line II
    394. Coins in a Line
    221. Maximal Square
    64. Minimum Path Sum
    [LeetCode] 129. Sum Root to Leaf Numbers Java
    [LeetCode] 117. Populating Next Right Pointers in Each Node II Java
    [LeetCode] 116. Populating Next Right Pointers in Each Node Java
    [LeetCode] 114. Flatten Binary Tree to Linked List Java
    [LeetCode] 113. Path Sum II Java
    [LeetCode] 112. Path Sum Java
  • 原文地址:https://www.cnblogs.com/qiyebao/p/4472440.html
Copyright © 2020-2023  润新知