设为首页 收藏本站
查看: 918|回复: 0

[经验分享] PostgreSQL 存储过程

[复制链接]

尚未签到

发表于 2016-11-19 08:59:57 | 显示全部楼层 |阅读模式
-- Function: tms_org_score_statis()
-- DROP FUNCTION tms_org_score_statis();
CREATE OR REPLACE FUNCTION tms_org_score_statis()
RETURNS character varying AS
$BODY$
declare
r record;
statis_sql "varchar";
execute_sql "varchar";
num int4 := 0;
total_score numeric(10,2);
begin
statis_sql := 'select tms.* from
(SELECT ORG.ID ORG_ID, COALESCE(AB.participation_legal, 0) participation_legal, COALESCE(AB.participation_leader, 0) participation_leader,
COALESCE(AB.participation_cadre, 0) participation_cadre, COALESCE(GH.participation_staff, 0) participation_staff,
COALESCE(AB.qualified_legal, 0) qualified_legal, COALESCE(AB.qualified_leader, 0) qualified_leader, COALESCE(AB.qualified_cadre, 0)qualified_cadre,
COALESCE(GH.qualified_staff, 0) qualified_staff, COALESCE(GH.avg_answer_time, 0) avg_answer_time,
CASE WHEN TSC.ORG_ID > 0 THEN TRUE ELSE FALSE END AS EXIST
FROM PUBLIC.T_ORG ORG
LEFT OUTER JOIN
(
SELECT BB.ORG_ID,
SUM(participation_legal) participation_legal,
SUM(participation_leader) participation_leader,
SUM(participation_cadre) participation_cadre,
SUM(qualified_legal) qualified_legal,
SUM(qualified_leader) qualified_leader,
SUM(qualified_cadre) qualified_cadre
FROM
(
SELECT AA.ORG_ID,
CASE WHEN AA.ROLE_ID = 1 THEN 5 ELSE 0 END AS participation_legal,
CASE WHEN AA.ROLE_ID = 2 THEN 3 ELSE 0 END AS participation_leader,
CASE WHEN AA.ROLE_ID = 3 THEN 2 ELSE 0 END AS participation_cadre,
CASE WHEN AA.ROLE_ID = 1 AND AA.AR = 10 THEN 5 ELSE 0 END AS qualified_legal,
CASE WHEN AA.ROLE_ID = 2 AND AA.AR = 10 THEN 3 ELSE 0 END AS qualified_leader,
CASE WHEN AA.ROLE_ID = 3 AND AA.AR = 10 THEN 2 ELSE 0 END AS qualified_cadre
FROM
(
SELECT US.ORG_ID, UR.ROLE_ID, MIN(ANSWER_RESULT) AR
FROM PUBLIC.T_USER US
LEFT OUTER JOIN PUBLIC.T_USER_ROLE UR
ON US.ID = UR.USER_ID
LEFT OUTER JOIN PUBLIC.T_QUESTION_PAPER QP
ON US.ID = QP.USER_ID
where ur.role_id in (1, 2, 3)
GROUP BY US.ORG_ID, UR.ROLE_ID
) AA
) BB
GROUP BY BB.ORG_ID
) AB
ON ORG.ID = AB.ORG_ID
left outer JOIN
(
select org_id, (all_real_qty::numeric * 30 / (participator_qty)) participation_staff,
(total_SCORE / all_real_qty) * 0.5 qualified_staff, total_answer_time / all_real_qty avg_answer_time
from
(
SELECT ORG_ID, COUNT(*) all_real_qty,MIN(participator_qty) participator_qty,
SUM(COALESCE(QP.score,0)) total_SCORE, COALESCE(sum(extract(epoch from (END_TIME - START_TIME))), 0) total_answer_time
FROM PUBLIC.V_USER_INFO VI
LEFT OUTER JOIN PUBLIC.T_QUESTION_PAPER QP
ON VI.USER_ID = QP.USER_ID
GROUP BY ORG_ID
) GG
) GH
ON ORG.ID = GH.ORG_ID
LEFT OUTER JOIN PUBLIC.t_competition_score TSC
ON ORG.ID = TSC.ORG_ID
) tms';
for r in execute statis_sql loop
total_score := r.participation_legal + r.participation_leader + r.participation_cadre + r.participation_staff + r.qualified_legal + r.qualified_leader + r.qualified_cadre + r.qualified_staff;
num := num + 1;
IF R.EXIST = false THEN
execute_sql := 'insert into public.t_competition_score(org_id,participation_legal,participation_leader, participation_cadre, participation_staff,
qualified_legal,qualified_leader,qualified_cadre,qualified_staff,avg_answer_time, total_score,create_time,status,last_update_time) values
(' || r.org_id || ',' || r.participation_legal || ',' || r.participation_leader || ',' || r.participation_cadre || ',' || r.participation_staff || ',' ||
r.qualified_legal || ',' || r.qualified_leader || ',' || r.qualified_cadre || ',' || r.qualified_staff || ',' || r.avg_answer_time || ',' ||
total_score || ', ''' || now() || ''',' || 20 || ',''' || now() || ''')';
END IF;
IF R.EXIST = true THEN
execute_sql := 'UPDATE public.t_competition_score set participation_legal = ' || r.participation_legal || ', participation_leader = ' || r.participation_leader || ', participation_cadre = '
|| r.participation_cadre || ', participation_staff = ' || r.participation_staff || ', qualified_legal = ' || r.qualified_legal || ', qualified_leader = ' || r.qualified_leader
|| ', qualified_cadre = ' || r.qualified_cadre || ', qualified_staff = ' || r.qualified_staff || ', avg_answer_time = ' || r.avg_answer_time || ', total_score = ' || total_score
|| ', last_update_time = ''' || now() || ''' where org_id = ' || r.org_id;
END IF;
RAISE NOTICE '%', 'sql: ' || execute_sql;
EXECUTE execute_sql;
end loop;
RETURN num;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
  perform org_id from t_competition_score where org_id = 1;
  if found then 
  raise notice 't';
  else 
  raise notice 'f';
  end if;
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;

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-302394-1-1.html 上篇帖子: rails postgreSQL schema 下篇帖子: PostgreSQL数据库恢复
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表