转载自:http://panyongzheng.iteye.com/blog/2194815

PostgreSQL的存储过程简单入门 http://blog.csdn.net/rachel_luo/article/details/8073458

存储过程事物  http://www.php100.com/manual/PostgreSQL8/tutorial-transactions.html  
PL/pgSQL - SQL存储过程语言  https://wiki.postgresql.org/wiki/9.1%E7%AC%AC%E4%B8%89%E5%8D%81%E4%B9%9D%E7%AB%A0

postgreSQL存储过程写法示例 http://blog.sina.com.cn/s/blog_448574810101f64u.html  
结构 
PL/pgSQL是一种块结构的语言,比较方便的是用pgAdmin III新建Function,填入一些参数就可以了。基本上是这样的:

Sql代码  
  1. CREATE OR REPLACE FUNCTION 函数名(参数1,[整型 int4, 整型数组 _int4, ...])
  2. RETURNS 返回值类型 AS
  3. $BODY$
  4. DECLARE
  5. 变量声明
  6. BEGIN
  7. 函数体
  8. END;
  9. $BODY$
  10. 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,$2,等等这样的标识符。有时候为了增强可读性,我们可以为 $n 参数名声明别名。然后通过这个别名或者数字标识符可以指向这个参数值。 
有两种方法创建一个别名。最好的方法是用CREATE FUNCTION命令给予这个参数一个名字,例如:

Sql代码  
  1. CREATE FUNCTION sales_tax(subtotal real) RETURNS real AS $$
  2. BEGIN
  3. RETURN subtotal * 0.06;
  4. END;
  5. $$ LANGUAGE plpgsql;

另一个方法是,在PostgreSQL 8.0之前唯一的方法,明确的用别名进行声明,用以下的语法进行声明: 
    name ALIAS FOR $n;  
这个风格的同一个例子看起来像下面这样 :

Sql代码  
  1. CREATE FUNCTION sales_tax(real) RETURNS real AS $$
  2. DECLARE
  3. subtotal ALIAS FOR $1;
  4. BEGIN
  5. RETURN subtotal * 0.06;
  6. END;
  7. $$ LANGUAGE plpgsql;

注意:这两个例子不是完全一样的。在第一种情况,subtotal可以用sales_tax.subtotal进行引用,但是在第二种情况下不能这么做。(如果我们给这个内部块附加了一个标签,subtotal能够替代这个标签) 
一些更多的例子:

Sql代码  
  1. CREATE FUNCTION instr(varchar, integer) RETURNS integer AS $$
  2. DECLARE
  3. v_string ALIAS FOR $1;
  4. index ALIAS FOR $2;
  5. BEGIN
  6. -- some computations using v_string and index here
  7. END;
  8. $$ LANGUAGE plpgsql;
  9. CREATE FUNCTION concat_selected_fields(in_t sometablename) RETURNS text AS $$
  10. BEGIN
  11. RETURN in_t.f1 || in_t.f3 || in_t.f5 || in_t.f7;
  12. END;
  13. $$ LANGUAGE plpgsql

当一个PL/pgSQL函数用输出参数来进行声明时,给予这个输出参数$n名和一个任意的别名跟正常输入参数是同样的方法。即使这个输出参数以NULL开始时也是一个有效的变量,它应该在函数的执行过程中被分配。这个参数最好的值将被返回。例如,这个sales-tax例子也可以用这种方法完成:

Sql代码  
  1. CREATE FUNCTION sales_tax(subtotal real, OUT tax real) AS $$
  2. BEGIN
  3. tax := subtotal * 0.06;
  4. END;
  5. $$ LANGUAGE plpgsql;

注意:我们省略了RETURNS real---我们可以将它包括在内,但它是多余的。 
当返回多个值的时候输出参数将非常有用,一个简单的例子是:

Sql代码  
  1. CREATE FUNCTION sum_n_product(x int, y int, OUT sum int, OUT prod int) AS $$
  2. BEGIN
  3. sum := x + y;
  4. prod := x * y;
  5. END;
  6. $$ LANGUAGE plpgsql;

如在Section 35.4.4中的讨论,这将为这个函数的结果创建一个匿名的记录类型。如果使用了RETURNS字句,那么必须给它指明RETURNS记录。 
另外一种方法声明PL/pgSQL函数是用RETURNS TABLE,例如:

Sql代码  
  1. CREATE FUNCTION extended_sales(p_itemno int)
  2. RETURNS TABLE(quantity int, total numeric) AS $$
  3. BEGIN
  4. RETURN QUERY SELECT quantity, quantity * price FROM sales
  5. WHERE itemno = p_itemno;
  6. END;
  7. $$ LANGUAGE plpgsql;

这跟声明一个或者多个OUT参数和制定RETURNS SETOF这些类型是同样的方法。 
当返回的PL/pgSQL函数的类型被声明为一个多态类型(anyelement, anyarray, anynonarray, 或者anyenum),特殊参数$0将被创建。它的数据类型将实际的返回函数的类型,从实际的输入类型返回(见Section 35.2.5)。这运行这个函数访问这个实际的返回类型如Section 39.3.3显示的那样。$0初始值为空并且能够被函数修改,如果需要,它可以用于保留返回值,虽然这不是必须的。$0也可以被给予一个别名。例如,这个函数能在任意一个有+操作符的数据类型上工作:

Sql代码  
  1. CREATE FUNCTION add_three_values(v1 anyelement, v2 anyelement, v3 anyelement)
  2. RETURNS anyelement AS $$
  3. DECLARE
  4. result ALIAS FOR $0;
  5. BEGIN
  6. result := v1 + v2 + v3;
  7. RETURN result;
  8. END;
  9. $$ LANGUAGE plpgsql

声明一个或者多个多态类型的输出参数也是同样的效果。这种情况下这个特殊的$0参数将不会被用到,这个输出参数本身也是同样的作用,例如:

Sql代码  
  1. CREATE FUNCTION add_three_values(v1 anyelement, v2 anyelement, v3 anyelement,
  2. OUT sum anyelement)
  3. AS $$
  4. BEGIN
  5. sum := v1 + v2 + v3;
  6. END;
  7. $$ LANGUAGE plpgsql;

39.3.2. 别名  
   newname ALIAS FOR oldname; 
这个ALIAS语法比以前的章节中介绍的更加普通:你可以为任意一个变量声明一个别名,不只是函数的参数。这实际的用途是用预定义的名字为变量定义不同的名字,如触发器过程中的NEW或者OLD。 例子:

Sql代码  
  1. DECLARE
  2. prior ALIAS FOR old;
  3. updated ALIAS FOR new;

因此,ALIAS使同样的对象有两种不同的方式命名,如果不限制的使用,将会变得混乱。这种方法最好只用于覆盖预定义的名字。

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

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;

下面的例子是要调用一个存储过程自动创建对应的一系列表:

Sql代码  
  1. CREATE OR REPLACE FUNCTION create_table_for_client(id int)
  2. RETURNS integer AS
  3. $BODY$
  4. DECLARE
  5. num int4 := 0;
  6. sql "varchar";
  7. BEGIN
  8. sql := 'create table _' || id || '_company(id int, name text)';
  9. EXECUTE sql;
  10. sql := 'create table _' || id || '_employee(id int, name text)';EXECUTE sql;
  11. sql := 'create table _' || id || '_sale_bill(id int, name text)';EXECUTE sql;
  12. .......
  13. return num;
  14. END;
  15. $BODY$ LANGUAGE plpgsql VOLATILE

自动创建序列 
第一个例子

Sql代码  
  1. CREATE OR REPLACE FUNCTION auto_gen_seq() RETURNS bigint AS
  2. $BODY$
  3. DECLARE
  4. rd RECORD;
  5. num int4 := 0;
  6. sql "varchar";
  7. seq_sql varchar;
  8. BEGIN
  9. sql := 'SELECT tablename FROM pg_tables WHERE tablename NOT LIKE ''pg%'' AND tablename NOT LIKE ''sql_%'' ORDER BY tablename;';
  10. FOR rd IN EXECUTE sql LOOP
  11. seq_sql:='CREATE SEQUENCE SQ_'||rd.tablename||' START 1000000 CACHE 30;';
  12. BEGIN
  13. EXECUTE seq_sql;
  14. EXCEPTION
  15. WHEN TOO_MANY_ROWS THEN
  16. RAISE EXCEPTION 'employee % not unique', seq_sql;
  17. WHEN OTHERS THEN
  18. return -1;
  19. END;
  20. num := num + 1;
  21. END LOOP;
  22. return num;
  23. END;
  24. $BODY$
  25. LANGUAGE plpgsql VOLATILE NOT LEAKPROOF
  26. COST 100;

调用:

Sql代码  
  1. select auto_gen_seq()

第二个例子

Sql代码  
  1. -- Function: auto_gen_seq(character)
  2. -- DROP FUNCTION auto_gen_seq(character);
  3. CREATE OR REPLACE FUNCTION auto_gen_seq("tbName" character)
  4. RETURNS character varying AS
  5. $BODY$/*
  6. 调用示例:
  7. SELECT tablename as tableName,
  8. 'sq_'||REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(tablename, 'tb_am_', ''), 'tb_sm_', ''), 'tb_pm_', ''), 'tb_pc_', ''), 'tb_ps_', ''), 'rh_', ''), 'TB_', ''), 'RH_', '' ), 'tb_', '') AS sqName
  9. ,auto_gen_seq(tablename||'') as successFlag,current_date,current_time FROM pg_tables WHERE tablename NOT LIKE 'pg%' AND tablename NOT LIKE 'sql_%' ORDER BY successFlag,tablename;
  10. */
  11. DECLARE
  12. rd RECORD;
  13. seq_sql varchar;
  14. flag_str varchar;
  15. sq_name varchar;
  16. sq_datetime varchar;
  17. BEGIN
  18. seq_sql:='create table _sequence_table ( id SERIAL not null, code VARCHAR(200) null, increment_num INT8 null, minvalue_num INT8 null, maxvalue_num INT8 null, start_num INT8 null, cache_num INT8 null, cycle_flag VARCHAR(100) null,create_datetime timestamp without time zone,constraint PK__SEQUENCE_TABLE primary key (id) );CREATE UNIQUE INDEX INDEX__sequence_table ON _sequence_table (code);';
  19. BEGIN
  20. EXECUTE seq_sql;
  21. EXCEPTION
  22. WHEN OTHERS THEN
  23. flag_str:='失败';
  24. END;
  25. --sq_name:=replace(replace($1, 'TB_', ''), 'RH_', '');
  26. --sq_name:=replace(replace(sq_name, 'tb_', ''), 'rh_', '');
  27. sq_name:='sq_'||REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE($1, 'tb_am_', ''), 'tb_sm_', ''), 'tb_pm_', ''), 'tb_pc_', ''), 'tb_ps_', ''), 'rh_', ''), 'TB_', ''), 'RH_', '' ), 'tb_', '');
  28. /*
  29. seq_sql:='drop SEQUENCE '||sq_name||';';
  30. BEGIN
  31. EXECUTE seq_sql;
  32. EXCEPTION
  33. WHEN OTHERS THEN
  34. flag_str:='失败';
  35. END;
  36. */
  37. seq_sql:='CREATE SEQUENCE '||sq_name||' START 1000000 CACHE 30;';
  38. BEGIN
  39. EXECUTE seq_sql;
  40. EXCEPTION
  41. WHEN OTHERS THEN
  42. return '失败,创建序列';
  43. END;
  44. sq_datetime:=to_timestamp(current_date||' '||current_time,'yyyy-mm-dd hh24:mi:ss') ;
  45. seq_sql:='INSERT INTO _sequence_table( code,increment_num,minvalue_num,start_num, cache_num,create_datetime) VALUES ( '''||sq_name||''',1,1000000,1000000, 30,'''||sq_datetime||''');';
  46. BEGIN
  47. EXECUTE seq_sql;
  48. EXCEPTION
  49. WHEN OTHERS THEN
  50. return '失败,插入序列信息';
  51. END;
  52. return '成功';
  53. END;
  54. $BODY$
  55. LANGUAGE plpgsql VOLATILE STRICT
  56. COST 100;
  57. ALTER FUNCTION auto_gen_seq(character)
  58. OWNER TO postgres;

调用

Sql代码  
  1. SELECT tablename as tableName,
  2. 'sq_'||REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(tablename, 'tb_am_', ''), 'tb_sm_', ''), 'tb_pm_', ''), 'tb_pc_', ''), 'tb_ps_', ''), 'rh_', ''), 'TB_', ''), 'RH_', '' ), 'tb_', '') AS sqName
  3. ,auto_gen_seq(tablename||'') as successFlag,current_date,current_time FROM pg_tables WHERE tablename NOT LIKE 'pg%' AND tablename NOT LIKE 'sql_%' ORDER BY successFlag,tablename;

postgreSQL存储过程写法示例相关推荐

  1. 数据库之postgreSQL存储过程写法示例

    PostgreSQL的存储过程简单入门 [url]http://blog.csdn.net/rachel_luo/article/details/8073458[/url] 存储过程事物 [url]h ...

  2. 【SQL Server】【存储过程】 存储过程写法示例

    公司做了一个需求,初期设想通过存储过程来初始化表数据,所以写了一个存储过程,如下: --CREATE PROCEDURE [dbo].[PROC_HANDLE_SHOPCAR_TXD_SR_TYPE] ...

  3. Mybatis调用PostgreSQL存储过程实现数组入参传递

    前言 项目中用到了Mybatis调用PostgreSQL存储过程(自定义函数)相关操作,由于PostgreSQL自带数组类型,所以有一个自定义函数的入参就是一个int数组,形如: CREATE OR ...

  4. 使用命令对象代替switch语句的写法示例

    使用命令对象代替switch语句的写法示例 http://www.jb51.net/article/61530.htm 转载于:https://www.cnblogs.com/hghrpg/p/456 ...

  5. Cmake的CMakeLists.txt写法示例

    Cmake的CMakeLists.txt写法示例 目录 示例一:单文件 示例二:多个源文件 示例三:将hello.c生成一个库来调用 示例四:工程分类文件夹编译 示例五:Cmake的install使用 ...

  6. jtree和mysql_Jtable和JTree的写法示例代码

    我们首先看看Jtable和JTree的基本概念和常用构造方法. 一:表格(JTable): 1.基本概念: 表格(JTable)是Swing新增加的组件,主要是为了将数据以表格的形式显示.给显示大块数 ...

  7. MySql存储过程异常处理示例

    MySql存储过程异常处理示例 参考文章: (1)MySql存储过程异常处理示例 (2)https://www.cnblogs.com/lucienbao/archive/2012/06/07/mys ...

  8. php mysql存储过程写法_mysql存储过程写法

    都说不懂数据库的程序员不是合格的程序员,那么你知道MySQL存储过程应该怎么写吗? MySQL存储过程写法 可以使用 CREATE PROCEDURE 语句创建存储过程. 数据库存储过程语法格式如下: ...

  9. mysql过程的写法,存储过程写法是什么,mysql存储过程写法

    存储过程写法是什么存储过程的写作是什么,存储过程的编写如下:1 .用代码[创建进程名]创建一个存储过程:2.用[EXECSP _ NAME]代码调用存储过程. 操作环境:Windows7系统,微软vi ...

最新文章

  1. javascript自动跳转
  2. SDCC 2015前端专场札记:Facebook、百度、腾讯、美团、饿了么等互联网公司的前端实战
  3. Python的locals()函数
  4. hive ALLOW_UNQUOTED_CONTROL_CHARS
  5. 创建 overlay 网络 - 每天5分钟玩转 Docker 容器技术(50)
  6. ejb 2.0 3.0_EJB 3.0注入和查找简介
  7. Java操作——获取文件扩展名,去掉文件扩展名
  8. matlab mtime,matlab中的视频分析工具箱 提供matlab中的视频分析工具 - 下载 - 搜珍网...
  9. php 公用方法,Laravel配置全局公共函数的方法步骤
  10. 基于图神经网络的图像分类,遥感图像分析
  11. Guava Cache 过期回源
  12. k8s重启节点状态NotReady
  13. 限期4个月:苹果严控版号,开发者将如何自救?
  14. 高速数据线缆自动化测试系统软件NSAT-1000
  15. 水晶报表各版本比较及相关释疑v2
  16. 网页透明flash代码
  17. 全新IT资源内控安全解决方案
  18. 从王者荣耀看设计模式(十.外观模式)
  19. 相似图片搜索原理二(phash—c++实现)
  20. 天正建筑T20图层英文变中文

热门文章

  1. vue下载excel直接上代码
  2. 李阳T恤衫疯狂英语100句
  3. Linux实现VLAN
  4. apksigner(一级命令)
  5. 20几岁,你的存款有多少?
  6. 什么是A股,什么是B股,什么是ST,什么是G
  7. mysql相除_mysql 常用函数
  8. 计算机网络资源共享实验过程,实验:局域网资源的共享
  9. JVM G1垃圾收集器
  10. .NET MVC用Ajax实现发送手机短信验证码