Postgresql 存储过程(plpgsql)两层for循环的操作
项目中遇到测试,需要造4500数据,而且需要分部门和日期,一个部门一天30条数据,剩下的铺垫数据可以一个部门一天100w左右数据,这里,每次变换部门,日期,需要操作至少300次,想到用存储过程写一个函数进行
首先,了解存储过程的语法:
CREATE[ORREPLACE]FUNCTION name([[argmode][argname]argtype[{DEFAULT|=}default_expr][,...]]) [RETURNSrettype |RETURNSTABLE(column_namecolumn_type[,...])] {LANGUAGElang_name |WINDOW |IMMUTABLE|STABLE|VOLATILE |CALLEDONNULLINPUT|RETURNSNULLONNULLINPUT|STRICT |[EXTERNAL]SECURITYINVOKER|[EXTERNAL]SECURITYDEFINER |COSTexecution_cost |ROWSresult_rows |SETconfiguration_parameter{TOvalue|=value|FROMCURRENT} |AS'definition' |AS'obj_file','link_symbol' }... [WITH(attribute[,...])] ————————————————
CREATE[ORREPLACE]FUNCTION--创建一个函数,若有此函数,即取代重新创建name-------函数名称
RETURNS---函数返回类型
具体的函数声明,请参考[postgresql存储过程]
下面说我写的函数:
CREATEORREPLACEFUNCTION"xue"."insert_into_table"() RETURNS"pg_catalog"."void"AS$BODY$ DECLAREtmpVARCHAR(1024); DECLAREninteger; DECLAREiinteger; DECLAREinst_seq_noCURSORFOR SELECTinst_seq_noFROMtwherenoin( '111','22','223','33','4358', '233','449','315','35335'); BEGIN RAISENOTICE'------------start----------'; i:=30; FORstmtINnoLOOP n:=30; FORnINn..iLOOP insertintotest2(NO, test_NO,TIME,USER_NO,SEQ_NO, NAME,USER_NO1,USER_NAME,CODE,USER_NO2,OPROR_NAME, REVIEW_TIME,DESC, VAL1,VAL2,DATE,UPD_TIME,DEL_FLAG)values (nextval('seq_test2'),n,'20190910',n,stmt.seq_no,n,n,n,n,n,n,'20190910','01','',n,n,'20190910', '20190909','0'); ENDLOOP; n=n+30; i=i+30; ENDLOOP; RAISENOTICE'-----------finished---------'; END; $BODY$ LANGUAGEplpgsqlVOLATILE COST100`
很简单的逻辑,但是在修改了三四遍才实现,这个第二次写存储过程,很多语法不是很熟悉,要注意的如:
1.`变量声明要用DECLARE
2.``游标CURSOR的用法
3.for循环要在begin中执行,
4.循环中要用“:=”
补充:Postgresql中存储过程(函数)调用存储过程(函数)时应用注意的问题
在postgresql中我们在执行存储过程中往往会使用select存储过程,但是如果存储过程中再调用存储过程时,就不能这样用了,应该用perform存储过程,可以去参考官方文档的说明
执行一个没有结果的表达式或者命令
有时候我们希望计算一个表达式或者一个命令,但是却丢弃其结果(通常因为我们经常调用一些存在有用的副作用但是不存在有用结果值的函数)。要在PL/pgSQL里干这件事,你可以使用PERFORM语句:
PERFORMquery;
这条语句执行一个query并且丢弃结果。query的写法和你平常写SQLSELECT命令是一样的,只是把开头的关键字SELECT替换成PERFORM。PL/pgSQL的变量和平常一样代换到命令中。同样,如果命令生成至少一行,那么特殊的变量FOUND设置为真,如果没有生成行,则为假。
注意:我们可能希望没有INTO子句的SELECT也能满足这样的需要,但是目前可以接受的唯一的方法是PERFORM。
一个例子:
PERFORMcreate_mv('cs_session_page_requests_mv',my_query);
以上为个人经验,希望能给大家一个参考,也希望大家多多支持毛票票。如有错误或未考虑完全的地方,望不吝赐教。