用PL/pgSQL寫postgreSQL的存儲過程

今天學會了用 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 ;
測試使用:
 

ALTER FUNCTION UpdateUserAccout(userid integer,nMoney integer)OWNER TO armory;

意思爲:讓armory用戶擁有使用UpdateUserAccout函數的權限

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/zhuzhubin/archive/2010/04/01/5442376.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章