X
首页 数据库相关软件开发 Informix-SPL(过程)语法详解(1)
Informix-SPL(过程)语法详解(1)

Informix数据库用户一般都熟悉的使用SQL语句进行简单的查询和统计,而在Informix-Online的数据库服务器中提供了用结构化查询语言SQL语句和流程控制存储语言SPL创建存储例程,以减少Informix的处理。存储例程是SQL语句和SPL的集合。它们存放在数据库中,SQL语句会被分析.优化,在例程的执行中,高速缓存中会有一执行规划,使后续操作的执行速度很快。而单独的SQL语句只有在执行时才会被优化,并且存储例程可以被不同的开发工具调用(4GL 、ESQL/C、POWERBUILDER.DELPHI),在SELECT语句中也调用过程。例程调试简单,不必重新编译应有软件包。在例程创建时Informix查询处理器会分析它,并产生一执行规划,永久存放于SPROCEDURES.SYSPROBODY.和SYSPROPLAN中,其后例程按此规划执行,由于大部分查询处理已经完成,存储例程可以在瞬间执行完毕。由于存储例程所具有的优越性,它已成为进行Informix数据库核心开发的有力工具,掌握它对Informix的开发人员有积极意义,现将我在实际工作中使用的语法和例子详解于下,疏漏和错误请来信指教。

1.创建和执行例程

  ①.创建例程语法:

      CRAETE PROCEDURE [OWNER.]PROCEDURE_NAME (参数1  参数类型=[DEFAULT], 参数2  参数类型=[DEFAULT],参数n  参数类型=[DEFAULT])

                    RETURNING

create procedure "test".upwage()

define rev_rev_item_code varchar(2,0);

define rev_p_rev_date date;

define acc_rec_prem_no decimal(8,2);define rev_p_rev_amt  decimal(10,2);define rev_I_info_branch varchar(6,0);define rev_I_info_appl_no decimal(8,0);define rev_I_info_date date;define rev_o_rev_date date;

define rev_o_rev_amt decimal(10,2);

define acc_ac_rev_amnt decimal(10,2);

define acc_rec_prem_date date;

begin work;

foreach cur_rev for select I_info_appl_branch,I_info_appl_no,I_info_date,

o_rev_date,o_rev_amt into rev_I_info_branch,

rev_I_info_appl_no,rev_I_info_date,rev_o_rev_date,                             rev_o_rev_amt from rev_rec_tbl where

(rev_item_code="PS" ) and p_rev_date is null and

p_rev_amt=0 and (I_info_appl_no is not null or

I_info_date is not null);

select max(rec_prem_acc_no) into acc_rec_prem_no from rec_prem_acc where                                   I_info_appl_branch=rev_I_info_branch

and I_info_appl_no=rev_I_info_appl_no

and I_info_date=rev_I_info_date

and o_rev_date=rev_o_rev_date

and rev_item_code="PS" and

ac_rev_amnt=rev_o_rev_amt;

select date(rec_prem_date) into acc_rec_prem_date

from rec_prem_acc where I_info_appl_branch=rev_I_info_branch

and I_info_appl_no=rev_I_info_appl_no

and I_info_date=rev_I_info_date

and o_rev_date=rev_o_rev_date

and rev_item_code="PS" and

ac_rev_amnt=rev_o_rev_amt and

rec_prem_acc_no=acc_rec_prem_no ;

select ac_rev_amnt into acc_ac_rev_amnt

  from rec_prem_acc

 where I_info_appl_branch=rev_I_info_branch

  and I_info_appl_no=rev_I_info_appl_no

  and I_info_date=rev_I_info_date

  and o_rev_date=rev_o_rev_date

  and rev_item_code="PS"

  and rec_prem_acc_no=acc_rec_prem_no

  and ac_rev_amnt=rev_o_rev_amt;

if acc_ac_rev_amnt is null or acc_rec_prem_date is null then

   continue foreach;

end if;

update rev_rec_tbl

   set p_rev_date=acc_rec_prem_date,
p_rev_amt =acc_ac_rev_amnt

 where I_info_appl_branch=rev_I_info_branch

   and I_info_date=rev_I_info_date

   and I_info_appl_no=rev_I_info_appl_no

   and o_rev_date=rev_o_rev_date;

end foreach;

commit work;

end procedure;

  ②.执行例程语法:

    A):在dbaccess中

       EXECUTE PROCEDURE DBNAME@SERVER_NAME:例程名(参数1,参数2,.....)用这种方法可对例程进行调试。

    B):在Informix-4GL中

       PREPARE PREP STATTEMENT FROM "EXECUTE PROCEDURE DBNAME@SERVER_NAME:例程名(?,?,?,...)

       DECLARE P_CURS SURSOR FOR PREP STMT

       OPEN P_CURS USING 参数1,参数2,....

       FETCH P_CURS INTO 返回值1,返回值2,...

       CLOSE P_CURS

       当应用程序不支持EXECUT PROCEDURE语法,则需使用PREPARE命令,如INFORMIX-4GL中,而使用INFORMIX-NEWEAR则无此限制,需注意的是PREPARE语句中变量用?号代替,其个数要与例程的参数个数和类型一致,返回值也是一样。

    C):在Informix-ESQL/C中

       EXEC SQL EXECUTE PROCEDURE 例程名(参数1,参数2,...) INTO (返回值1,返回值2,...)在EC5.0或更高版本可使用EXECUTE PROCEDURE 语法,在ESQL/C中宿主变量用于想存储例程传递值,同时也接收返回值.

    D):在POWER BUILDER中

       DECLARE 逻辑名 PROCEDURE FOR 例程名(:参数1,:参数2:...) INTO :返回值1,:返回值2,..USING 事物名

       EXEC 例程名(:参数1,:参数2,.....)

       PB要求为例程制定逻辑名,以后的SQL语句将以逻辑名为准指向后台数据库例程,当例程即便没有参数也必须有小扩号.

 

2.流程控制语言:

在过程中也提供了其他语言具备的流程控制语言,完成循环判断和分类处理的能力,主要有:①.IF ....ELIF.....ELSE.....END IF例:

CRAETE PROCEDURE STR_COM(STR1 CHAR(20),STR2 CHAR(20))

RETURNING INT;

DEFINE REL INT;

IF STR1>STR2 THEN  --当STR1>STR2 REL=1

LET REL=1;

ELIF STR2>STR1 THEN --当STR2>STR1 REL=-1

LET REL=-1;

ELSE

LET REL=0;   --当STR1=STR2 REL=0

END IF

RETUEN REL;

END PROCEDURE

当IF的条件为一个SQL语句如SELECT时需用扩号,并且返回值为单值。

②.FOR .....END FOR

例:FOR INDEX IN (20 TO 30 STEP 2,100 TO 200 STEP 10)

   --执行代码

   END FOR

FOR的条件可以是变量,常量或一个SQL语句的返回值

③.WHILE.......END WHILE

当WHILE的条件为TRUE时执行WHILE后的语句,为FALSE退出循环。

例:WHILE I<10

    INSERT INTO TBB_1 VALUES(I);

    LET I=I+1;

    END WHILE;

④.FOREACH........END FOREACH

该语句较为特别FOREACH循环能够声明并打开游标,读取记录行,并关闭游标.其完整语法:

 FOREACH 游标名 [WITH HOLD] SELECT 字段名 INTO 变量 FROM

   TABLE WHERE 条件 ;

 END FOREACH

 FOREACH EXECUTE PROCEDURE 例程名(参数1,参数2,..) INTO

  变量

 END FOREACH

该循环中语句的执行次数与SELECT 和 EXECUTE PROCEDURE语句返回的行数一样多。如果FOREACH语句中包含一条EXECUTE PROCEDURE,则循环停止的条件为:

.执行了不带任何参数的RETURN语句

.执行了END PROCEDURE

如果没有返回行数据,则不再执行循环中的语句。存储例程中不允许使用滚动游标。

当使用WITH HOLD时,更新游标将放置更新锁,使其他过程无法更新该行,直至事物完成,当在FOREACH循环的语句块中的UPDATE或DELETE有

WHERE CURRENT OF短语,则存储例程会自动使用更新游标

例1:BEGIN WORK;

     FOREACH CUR_1 FOR SELECT DATE INTO V_DATE FROM TABLE
 IF V_DATE IS NULL THEN

     DELETE FROM TABLE WHERE CURRENT OF CUR_1;

     END IF;

     END FOREACH;

     COMMIT WORK;

例2:FOREACH EXECUTE PROCEDURE BAR(10,20) INTO I

     INSERT INTO TABLE1 VALUES(I)

     END PROCEDURE

⑤.CONTINUE    适用语句( FOR WHILE FOREACH)   将执行传递给下一次循环⑥.EXIT

   适用语句( FOR WHILE FOREACH)

   从循环中退出

   例:FOR J=1 TO 20

       IF J>10 THEN

          CONTINUE FOR;

       END IF

       LET I,S=J,0;

         WHILE I>0

             LET I=I-1;

             IF I=5 THEN

               EXIT FOR;

             END IF

         END WHILE

       END FOR