postgreSQL存储过程写法示例

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

Postgresql的存储过程简单入门http://www.jb51.cc/article/p-wipiavos-bda.html

存储过程事物 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,填入一些参数就可以了。基本上是这样的:
  1. CREATEORREPLACEFUNCTION函数名(参数1,[整型int4,整型数组_int4,...])
  2. RETURNS返回值类型AS
  3. $BODY$
  4. DECLARE
  5. 变量声明
  6. BEGIN
  7. 函数
  8. END;
  9. 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
其他
还有几个常用的函数
SELECT INTO record …; 表示将select的结果赋给record变量(RECORD类型)
PERFORM query; 表示执行query并丢弃结果
EXECUTE sql; 表示执行sql语句,这条可以动态执行sql语句(特别是由参数传入构造sql语句的时候特别有用)
参数: 传递给函数的参数都是用 $1,$2,等等这样的标识符。有时候为了增强可读性,我们可以为 $n 参数名声明别名。然后通过这个别名或者数字标识符可以指向这个参数值。
有两种方法创建一个别名。最好的方法是用CREATE FUNCTION命令给予这个参数一个名字,例如:
CREATEFUNCTIONsales_tax(subtotalreal)RETURNSrealAS$$
  • RETURNsubtotal*0.06;
  • $$LANGUAGEplpgsql;

  • 一个方法是,在Postgresql 8.0之前唯一的方法,明确的用别名进行声明,用以下的语法进行声明:
    name ALIAS FOR $n; 这个风格的同一个例子看起来像下面这样 :
    FUNCTIONsales_tax( subtotalALIASFOR$1;
  • 注意:这两个例子不是完全一样的。在第一种情况,subtotal可以用sales_tax.subtotal进行引用,但是在第二种情况下不能这么做。(如果我们给这个内部块附加了一个标签,subtotal能够替代这个标签
    一些更多的例子:
    FUNCTIONinstr(varchar,integer)integer v_stringalIASindexALIASFOR$2;
  • --somecomputationsusingv_stringandindexhere
  • $$LANGUAGEplpgsql;
  • FUNCTIONconcat_selected_fields(in_tsoMetablename)RETURNStextRETURNin_t.f1||in_t.f3||in_t.f5||in_t.f7;
  • $$LANGUAGEplpgsql

  • 一个PL/pgsql函数输出参数来进行声明时,给予这个输出参数$n名和一个任意的别名跟正常输入参数是同样的方法。即使这个输出参数以NULL开始时也是一个有效的变量,它应该在函数的执行过程中被分配。这个参数最好的值将被返回。例如,这个sales-tax例子也可以用这种方法完成:
    real,85); font-weight:bold">OUTtax tax:=subtotal*0.06;
  • 注意:我们省略了RETURNS real---我们可以将它包括在内,但它是多余的。
    当返回多个值的时候输出参数将非常有用,一个简单的例子是:
    FUNCTIONsum_n_product(xint,yOUTsumOUTprodint) sum:=x+y;
  • prod:=x*y;
  • 如在Section 35.4.4中的讨论,这将为这个函数的结果创建一个匿名的记录类型。如果使用了RETURNS字句,那么必须给它指明RETURNS记录。
    另外一种方法声明PL/pgsql函数是用RETURNS TABLE,例如:
    FUNCTIONextended_sales(p_itemnoint)
  • TABLE(quantitynumeric)RETURNQUERYSELECTquantity,quantity*priceFROMsales
  • WHEREitemno=p_itemno;
  • 这跟声明一个或者多个OUT参数和制定RETURNS SetoF这些类型是同样的方法
    当返回的PL/pgsql函数的类型被声明为一个多态类型(anyelement,anyarray,anynonarray,或者anyenum),特殊参数$0将被创建。它的数据类型将实际的返回函数的类型,从实际的输入类型返回(见Section 35.2.5)。这运行这个函数访问这个实际的返回类型如Section 39.3.3显示的那样。$0初始值为空并且能够被函数修改,如果需要,它可以用于保留返回值,虽然这不是必须的。$0也可以被给予一个别名。例如,这个函数能在任意一个有+操作符的数据类型上工作:
    FUNCTIONadd_three_values(v1anyelement,v2anyelement,v3anyelement)
  • RETURNSanyelement resultALIASFOR$0;
  • result:=v1+v2+v3;
  • RETURNresult;
  • 声明一个或者多个多态类型的输出参数也是同样的效果。这种情况下这个特殊的$0参数将不会被用到,这个输出参数本身也是同样的作用,例如:
    sumanyelement)
  • sum:=v1+v2+v3;
  • 39.3.2. 别名 newname ALIAS FOR oldname;
    这个ALIAS语法比以前的章节中介绍的更加普通:你可以为任意一个变量声明一个别名,不只是函数的参数。这实际的用途是用预定义的名字为变量定义不同的名字,如触发器过程中的NEW或者OLD。 例子:
    priorALIASFORold;
  • updatedaliASFORnew;

  • 因此,ALIAS使同样的对象有两种不同的方式命名,如果不限制的使用,将会变得混乱。这种方法最好只用于覆盖预定义的名字。
    最后,贴出解决上面这个问题的存储过程吧:
    FUNCTIONmessage_deletes(ids"varchar",useridint8)
  • RETURNSint4 rRECORD;
  • delbool;
  • numint4:=0;
  • sql"varchar";
  • sql:='selectid,receiveuserid,senduserid,senddelete,receivedeletefrommessagewhereidin('||ids||')';
  • FORrINEXECUTEsqlLOOP
  • del:=false;
  • IFr.receiveuserid=useridandr.senduserid=useridTHEN
  • true;
  • ELSEIFr.receiveuserid=userid IFr.senddelete=falseupdatemessagesetreceivedelete=truewhereid=r.id;
  • ELSE
  • ENDIF;
  • ELSEIFr.senduserid=userid IFr.receivedelete=setsenddelete= IFdeldeletefrommessage num:=num+1;
  • ENDLOOP;
  • returnnum;
  • LANGUAGE'plpgsql'VOLATILE;

  • 下面的例子是要调用一个存储过程自动创建对应的一系列表:
    FUNCTIONcreate_table_for_client(id sql:='createtable_'||id||'_company(idint,nametext)';
  • EXECUTEsql;
  • sql:='createtable_'||id||'_employee(idint,nametext)'; sql:='createtable_'||id||'_sale_bill(idint,250); line-height:18px"> .......
  • $BODY$LANGUAGEplpgsqlVOLATILE

  • 自动创建序列
    一个例子
    FUNCTIONauto_gen_seq()bigint rdRECORD;
  • seq_sqlvarchar;
  • sql:='SELECTtablenameFROMpg_tablesWHEREtablenameNOTLIKE''pg%''ANDtablenameNOTLIKE''sql_%''ORDERBYtablename;';
  • FORrd seq_sql:='CREATESEQUENCESQ_'||rd.tablename||'START1000000CACHE30;';
  • EXECUTEseq_sql;
  • EXCEPTION
  • WHENTOO_MANY_ROWS RAISEEXCEPTION'employee%notunique',seq_sql;
  • WHENOTHERSreturn-1;
  • LANGUAGEplpgsqlVOLATILENOTLEAKPROOF
  • COST100;

  • 调用:
    selectauto_gen_seq()
    第二个例子
    --Function:auto_gen_seq(character)
  • --DROPFUNCTIONauto_gen_seq(character);
  • FUNCTIONauto_gen_seq("tbName"character)
  • charactervarying $BODY$/*
  • 调用示例:
  • SELECTtablenameastableName,250); line-height:18px"> 'sq_'||REPLACE(REPLACE(tablename,'tb_am_',''),'tb_sm_','tb_pm_','tb_pc_','tb_ps_','rh_','TB_','RH_','tb_','')ASsqName
  • ,auto_gen_seq(tablename||'')assuccessFlag,85); font-weight:bold">current_date,85); font-weight:bold">current_timeFROMpg_tablesWHEREtablenameNOTLIKE'pg%'ANDtablenameLIKE'sql_%'ORDERBYsuccessFlag,tablename;
  • */
  • flag_str sq_name sq_datetime seq_sql:='createtable_sequence_table(idSERIALnotnull,codeVARCHAR(200)null,increment_numINT8null,minvalue_numINT8null,maxvalue_numINT8null,start_numINT8null,cache_numINT8null,cycle_flagVARCHAR(100)null,create_datetimetimestampwithouttimezone,constraintPK__SEQUENCE_TABLEprimarykey(id));CREATEUNIQUEINDEXINDEX__sequence_tableON_sequence_table(code);';
  • flag_str:='失败';
  • --sq_name:=replace(replace($1,'TB_',''),'RH_','');
  • --sq_name:=replace(replace(sq_name,'tb_','rh_',250); line-height:18px"> sq_name:='sq_'||REPLACE($1,'');
  • /*
  • seq_sql:='dropSEQUENCE'||sq_name||';';
  • seq_sql:='CREATESEQUENCE'||sq_name||'START1000000CACHE30;';
  • return'失败,创建序列';
  • sq_datetime:=to_timestamp(current_date||''||current_time,'yyyy-mm-ddhh24:mi:ss');
  • seq_sql:='INSERTINTO_sequence_table(code,increment_num,minvalue_num,start_num,cache_num,create_datetime)VALUES('''||sq_name||''',1,1000000,30,'''||sq_datetime||''');';
  • return'成功';
  • LANGUAGEplpgsqlVOLATILESTRICT
  • COST100;
  • ALTERFUNCTIONauto_gen_seq( OWNERTOpostgres;

  • 调用

    相关文章

    项目需要,有个数据需要导入,拿到手一开始以为是mysql,结果...
    本文小编为大家详细介绍“怎么查看PostgreSQL数据库中所有表...
    错误现象问题原因这是在远程连接时pg_hba.conf文件没有配置正...
    因本地资源有限,在公共测试环境搭建了PGsql环境,从数据库本...
    wamp 环境 这个提示就是说你的版本低于10了。 先打印ph...
    psycopg2.OperationalError: SSL SYSCALL error: EOF detect...