<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    漁人碼頭

    天行健,君子以自強不息。地勢坤,君子以厚德載物。
    posts - 12, comments - 16, trackbacks - 0, articles - 43
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

    Informix-SPL(過程)語法詳解

    Posted on 2006-12-14 14:27 Fisher 閱讀(2932) 評論(0)  編輯  收藏 所屬分類: DataBase
    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?值1類型,值2類型,值n類型;?

    ??????<......>;語句體;??????END?RPOCEDURE?

    例程大小不可超過64K,這包括所有的SQL.SPL.空格.跳格符,例程名最多18個字符,并在數據庫中唯一存在,語句間用";"分隔,例程只能在當前數據庫中創建,例程創建后是一標準?

    執行模板塊,可在不同的應有中對其調用,這對開發不同版本的應用將更為便利。例:?

    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?

    3.變量的定義與賦值:?

    ???存儲例程中使用的變量必須在例程開始處用DEFINE語句定義,變量的數據類型為除SERIAL以外的任意類型,如果定義一個TEXT或BYTE類型的變量,則該變量為指向數據的指針。傳遞給程序的變量必須在CRAETE?PROCEDURE語句中定義。DEFINE也可使用LIKE語句。變量類型缺省為局部變量,也可引用GLOBAL定義全局變量,全局變量在例程間保持它的值,直至會話結束。用戶必須為每一個定義的全局變量賦缺省值,缺省值僅在例程第一次引用該全局變量時使用,以后的例程將會忽略其缺省值。?

    ??例:CREATE?PROCEDURE?SP1()?

    ????????RETURNING?INT;?

    ????????DEFINE?GLOBAL?I?INT?DEFAULT?1;?

    ????????LET?I=I+1;?

    ????????RETURN?I;?

    ??????END?PROCEDURE?

    ??????CRAETE?PROCEDURE?SP2?()?

    ????????RETURNING?INT;?

    ????????DEFINE?GLOBAL?I?INT?DEFAULT?4;?

    ????????LET?I=I+1;?

    ????????RETURN?I;?

    ??????END?PROCEDURE?

    ?????當執行順序為SP1,SP2?返回值3,當執行順序為SP2,SP1返回值為6。?

    ?????例程也可被聲名為變量?

    ??例:DEFINE?LEN?PROCEDURE?

    ??????LET?X=LEN(A,B,C)?

    ????變量賦值必須用LET關鍵字,如果不給變量賦值,變量會有一個不確定值,任何對該變量的使用都會產生錯誤。?

    ??????BEGIN......END?

    ?利用BEGIN....END可以封裝語句,它允許用戶完成以下功能:?

    ?????.定義僅用于該語句塊的變量?

    ?????.在語句塊內以不同方式處理異常情況.?

    ?????.在某語句塊中定義的變量,在該語句塊以及它所包含的語句塊都有效,除非又將變量定義一次。?

    ??????例?:?CREATE?PROCEDURE?SP?()?

    ???????????RETURNING?INT;?

    ???????????DEFINE?V1?INT;?

    ???????????LET?V1=1;?

    ???????????BEGIN?

    ?????????????DEFINE?V1?INT;?

    ?????????????LET?V1=2;?

    ???????????END?

    ??????????RETURN?V1;?

    ????????END?PROCEDURE?

    ???返回值為1。?

    4.在例程中執行其他例程和系統命令:?

    ???應用CALL命令可在例程中調用其他的例程。?

    ???例:CREATE?PROCEDURE?SP()?????

    ???????DEFINE?I,J,K,L?INT;?

    ?????????CALL?SP1(10,20)?RETURNING?I,J,K;?

    ???????END?PROCEDURE?

    ???用SYSTEM可在例程中調用系統命令。?通過SYSTEM命令,用戶可以執行操作系統命令。系統命令放在括號內,用雙管道號(||),還可以為SYSTEM命令串連起多個表達式。但在存儲例程中不能使用該命令的返回值,如果系統調用失敗(返回非零值),返回值將和SQL錯誤代碼一起,放在ISAM代碼中。?

    ????例:SYSTEM?"/usr/exec/exec.sh"?

    ????用RETURN命令可以將例程運行的結果返回給調用它的應用。當需要多次調用同一例程可執行RETURN?WITH?RESUME命令,它可以保證下一次調用該例程時,所有變量保持原值,而且從RETURN?WITH?RESUME后的第一條語句執行。?

    ????例:RETURN?V_INT?WITH?RESUME;?

    5.調試跟蹤語句:?

    ???我們在做應用的時候,當程序完成后都需要進行數據測試,以便驗證程序邏輯的嚴密性,在例程中,INFORMIX也提供了調試跟蹤語句,其主要有(TRACE,ON?EXCEPTION,RAISE?EXCEPTION)。TRACE?語句可以跟蹤語句塊中每一個活動語句的結果和過程,并且可用SET?DEBUG?FILE?TO?FILENAME?語法寫入指定文件中。?

    ????ON?EXECEPTION可在例程中設定斷點,向一個DEBUGLOG或ERRLOG文件寫入錯誤信息。完整語法為:?

    ????ON?EXCEPTION?IN?(error_number)?

    ???????set?sql錯誤代碼變量,isam錯誤代碼變量,錯誤信息變量?

    ???????處理語句?

    ????END?EXCEPTION?WITH?RESUME?

    ????注意SET后的3個變量必須在DEFINE中定義,其中sql錯誤代碼.Isam錯誤代碼變量類型為INT,錯誤信息變量為足夠長的CHAR變量。Error_number是一個SQL錯誤代碼或用RAISE?EXCEPTION設置的陷阱代碼。WITH?RESUME為可選項,當用WITH?RESUME語句時,INFORMIX會執行完ON?EXCEPTION語句塊的命令后會返回到出錯命令行的下一行接著執行,或RAISE?EXCEPTION的下一行執行。?

    ????RAISE?EXCEPTION人為設定SQL錯誤代碼,ISAM錯誤代碼,錯誤信息。?

    ????RAISE?EXCEPTION與ON?EXCEPTION語法連用很容易跟蹤例程的錯誤代碼?

    ?例:CREATE?PROCEDURE?TMP_PROCEDURE()?

    ???????DEFINE?SQLCODE?INT;?

    ???????DEFINE?ISAMCODE?INT;?

    ???????DEFINE?ERR_TXT?CHAR(255);?

    ??????ON?EXCEPTION?SET?SQLCODE,ISAMCODE,ERR_TXT?

    ????????IF?SQLCODE=?-284?THEN?

    ???????????RASIE?EXCEPTION?SQLCODE,ISAMCODE,"在TMP_PROCEDURE中查詢返回多條記錄";?

    ????????END?IF?

    ????????IF?SQLCODE=?-1218?THEN?

    ???????????RASIE?EXCEPTION?SQLCODE,ISAMCODE,"在TMP_RPOCEDURE中類型轉換錯誤“;?

    ???????END?IF?

    ?????END?EXCEPTION?

    ??????SELECT?.......?

    END?PROCEDURE?

    ??

    6.過程實例:?

    CREATE?PROCEDURE?YEARS(E_DATE?DATE,B_DATE?DATE)?

    RETURNING?INT;返回E_DATE與B_DATE之間的整年數(E_DATE大于B_DATE)?

    ????DEFINE?V_E??INT;?

    ????DEFINE?V_B??INT;?

    ????LET?V_E?=?MONTH(E_DATE);?

    ????LET?V_B?=?MONTH(B_DATE);?

    ????IF?V_E?<?V_B?THEN?

    ???????LET?V_E?=?YEAR(E_DATE)-YEAR(B_DATE)-1;?

    ???????RETURN?V_E;?

    ????ELIF?V_E?>;?V_B?THEN?

    ???????LET?V_E?=?YEAR(E_DATE)-YEAR(B_DATE);?

    ???????RETURN?V_E;?

    ????END?IF;?

    ????LET?V_E?=?DAY(E_DATE);?

    ????LET?V_B?=?DAY(B_DATE);?

    ????IF?V_E?<?V_B?THEN?

    ???????LET?V_E?=?YEAR(E_DATE)-YEAR(B_DATE)-1;?

    ???????RETURN?V_E;?

    ????ELSE?

    ???????LET?V_E?=?YEAR(E_DATE)-YEAR(B_DATE);?

    ???????RETURN?V_E;?

    ????END?IF;?

    END?PROCEDURE;
    主站蜘蛛池模板: 无码专区一va亚洲v专区在线| 亚洲白色白色在线播放| 亚洲综合一区二区三区四区五区| 亚洲精品美女久久7777777| 中国在线观看免费国语版| 亚洲国产精品嫩草影院久久| 国产亚洲漂亮白嫩美女在线| 国产午夜免费福利红片| 黄色免费网站在线看| 2022中文字字幕久亚洲| 香蕉免费看一区二区三区| 成全视频在线观看免费高清动漫视频下载 | 乱人伦中文视频在线观看免费| 亚欧日韩毛片在线看免费网站| 国产99视频免费精品是看6| 国产亚洲福利精品一区二区| 亚洲一区免费在线观看| 久久亚洲国产成人影院| 日韩内射激情视频在线播放免费 | 免费v片在线观看无遮挡| 人体大胆做受免费视频| 亚洲va无码va在线va天堂| 春暖花开亚洲性无区一区二区| 亚洲成人免费电影| 国产 亚洲 中文在线 字幕| 国产成人高清精品免费软件| 亚洲AV无码乱码在线观看代蜜桃 | 久久亚洲伊人中字综合精品| 暖暖日本免费中文字幕| 亚洲国产精品无码久久九九| 黄色免费在线网站| 亚洲日韩精品一区二区三区无码 | 久久免费精品一区二区| 亚洲色图视频在线观看| 爽爽日本在线视频免费| 国产在线精品一区免费香蕉| 亚洲色一色噜一噜噜噜| 91精品免费国产高清在线| 久久久亚洲裙底偷窥综合| 日本在线看片免费人成视频1000| 婷婷久久久亚洲欧洲日产国码AV|