oracle通过job调用存储过程.docx
这是本人第一次处理ORACLE的存储过程以及计划任务(JOB)的事情;期间遇到了很多问题在此将这次试用JOB调用自己的编写的存储过程的过程中遇到的问题做一总结;任务实时采集系统会每5分钟给中心系统传送一个流量数据,但是没有给出累计流量数据;1、编写一个存储过程WATERQCAL用于计算流量增量以及得出最后的累计流量;2、用一个任务计划每隔5分钟,统一进行执行一次WATERQCAL存储过程;创建存储过程代码如下CREATEORREPLACEPROCEDUREWATERQCALAS如果用引号将存储过程名引起来后就会保存成WATERQCAL存储过程;如果不引起来的话最终保存的是WATERQCAL;OLDACC_WNUMBEROLDACC_W_PQNUMBERNEWACC_WNUMBERBEGINDECLARE查询出一个集合CURSORMPCD_NUMBERISSELECTDISTINCTMP_CDFROMWR_MP_Q_RWHEREACC_WISNULL定义行游标变量RCD_NUMBERMPCD_NUMBERROWTYPE循环开始BEGIN开启游标OPENMPCD_NUMBERLOOP开始游标循环操作FETCHMPCD_NUMBERINTORCD_NUMBEREXITWHENMPCD_NUMBERNOTFOUND开始查询某一个个测站数据DECLARE查询出一个某测站的所有未计算浏览的集合CURSORSINSTBISSELECTFROMWR_MP_Q_RWHEREACC_WISNULLANDMP_CDRCD_NUMBERMP_CDORDERBYTMASC定义行游标变量SINSTSINSTBROWTYPEBEGIN开启单站游标OPENSINSTBLOOPFETCHSINSTBINTOSINSTEXITWHENSINSTBNOTFOUNDBEGIN开始计算流量查询出最有一条计算过流量的记录BEGINSELECTACC_WINTOOLDACC_WFROMWR_MP_Q_RWHEREACC_WISNOTNULLANDMP_CDSINSTMP_CDANDROWNUM1ORDERBYTMDESCEXCEPTION处理异常没有数据时;该如何处理;因为有异常处理此处的SELECT语句以及异常都必须单独用BEGINEND括起来;WHENNO_DATA_FOUNDTHENOLDACC_W0END计算流量增量OLDACC_W_PQABSSINSTMP_Q/12计算当前累计流量NEWACC_WABSOLDACC_WABSOLDACC_W_PQ更新当前累计流量UPDATEWR_MP_Q_RSETACC_WNEWACC_WWHEREMP_CDSINSTMP_CDANDTMSINSTTMENDENDLOOPCLOSESINSTB关闭游标ENDENDLOOPCLOSEMPCD_NUMBERENDEND创建ORACLE计划任务的代码如下DECLAREJOBNUMNUMBERBEGINSYSDBMS_JOBJOBJOBNUM,WHAT SWATERWATERQCAL ,NEXT_DATETRUNCSYSDATE18/1440,INTERVAL TRUNCSYSDATE, MI 18/1440 COMMITEND/通过PLSQL工具创建在编制存储过程时应该注意的是1、每一个语句结束时都必须采用;结束。否则会报SQL语句不完整;2、CREATEORREPLACEPROCEDUREPROCEDURE_NAMEAS该语句部分PROCEDURE_NAME不能够用引号引起来;如果引号引起来的话,名字中的小写字母之类的还会原样保留;但是ORACLE默认是需要将存储过程的名字转换成大写的;并且后面创建JOB是如果输入之前带小写字母的名字时又会转换成大写的时候就会报找不到存储过程;3、FOR循环来操作游标,不用OPEN游标以及CLOSE游标操作否则会报错;4、针对每一个包含异常处理语句的SQL都必须防止在BEGIN以及END之中;否则可能会出现部分语句不执行,直接跳转到下一个END处;5、循环处理1)、FOR循环FORINLOOP执行语句ENDLOOP1循环遍历游标CREATEORREPLACEPROCEDURETESTASCURSORCURSORISSELECTNAMEFROMSTUDENTNAMEVARCHAR20BEGINFORNAMEINCURSORLOOPBEGINDBMS_OUTPUTPUTLINENAMEENDENDLOOPENDTEST2循环遍历数组CREATEORREPLACEPROCEDURETESTVARARRAYINMYPACKAGETESTARRAYAS输入参数VARARRAY是自定义的数组类型,定义方式见标题6INUMBERBEGINI1存储过程数组是起始位置是从1开始的,与JAVA、C、C等语言不同。因为在ORACLE中本是没有数组的概念的,数组其实就是一张表TABLE,每个数组元素就是表中的一个记录,所以遍历数组时就相当于从表中的第一条记录开始遍历FORIIN1VARARRAYCOUNTLOOPDBMS_OUTPUTPUTLINETHENO||I||RECORDINVARARRAYIS||VARARRAYIENDLOOPENDTEST2、WHILE循环WHILE条件语句LOOPBEGINENDENDLOOPEGCREATEORREPLACEPROCEDURETESTIINNUMBERASBEGINWHILEI SWATERWATERQCAL 的WATERQCAL的存储过程名必须以结尾;否则会报如下错误ERRORA06550第1行,第110列PLS00103出现符号“END“在需要下列之一时符号““被替换为“END“后继续。ORA06512在“SYSDBMS_JOB“,LINE82ORA06512在“SYSDBMS_JOB“,LINE140ORA06512在LINE32、如果前面创建存储过程中将存储过程名用引号引起来后,因为存储郭晨被保存成了WATERQCAL;而WHAT中指定的存储过程SWATERWATERQCAL会被转换SWATERWATERQCAL;所以会报如下错误ERRORA06550第1行,第93列PLS00201必须声明标识符 SWATERWATERQCAL ORA06550第1行,第93列PL/SQLSTATEMENTIGNOREDORA06512在“SYSDBMS_JOB“,LINE82ORA06512在“SYSDBMS_JOB“,LINE140ORA06512在LINE33、时间间隔设置必须是在指定的时间必须是当前时间的后面的值(即如果由INTERVAL计算出来的NEXTTIME如果在当前时间之前,会怎么处理就没法处理,会报错),否则会报如下错误ORA23420间隔必须以将来的一个时间作评估ORA06512在“SYSDBMS_JOB“,LINE57ORA06512在“SYSDBMS_JOB“,LINE134ORA06512在LINE34、如果SYSDBMS_JOBJOBJOB,用的是JOB作为参数,并且是通过查询语句执行的话会报如下错误ERRORA01008并非所有变量都已