posts - 297,  comments - 1618,  trackbacks - 0

          1、簡介
                  存儲過程(Stored Procedure)是一組為了完成特定功能的SQL語句集,經編譯后存儲在數據庫中。用戶通過指定存儲過程的名字并給出參數(如果該存儲過程帶有參數)來執行它。存儲過程是數據庫中的一個重要對象,任何一個設計良好的數據庫應用程序都應該用到存儲過程。
                  存儲過程是由流控制和SQL語句書寫的過程,這個過程經編譯和優化后存儲在數據庫服務器中,應用程序使用時只要調用即可。
          2、重要概念和疑問解答
                  1)何謂informix中的SPL?
                  SPL(Stored Procedure Language)是informix中提供的一種提供流程控制(分支和循環)的SQL。它包括SPL過程(沒有返回值)和SPL函數(有返回值)。SPL將在創建的時候被解析和優化,它以可執行的方式保存在system catalog表中。
                  2)使用SPL為什么會改善性能?
                  i)因為它運行在informix引擎中,所以減少了I/O;
                  ii)降低了應用的復雜性;
                  iii)對頻率較高的重復操作使用更好。
                  3)SPL的靈活性表現在哪些部分?
                  i)它可在其它SQL語法中被調用;
                  ii)它也可以在觸發器中使用;
                  iii)可在SQL中添加流程控制;
                  iv)很容易維護。
                 4)SPL的參數
                 i)可以傳遞很多個參數;
                 ii)SPL的參數的最大限制是32K;
                 iii)除了如下兩種外可以是任何一種SQL數據類型:
                       Serial/Serial8
                       Text/Byte (能夠使用REFERENCES關鍵字傳遞)。
                 iv)能夠使用很復雜或者用戶自定義的數據類型;
                 v)可以通過default為參數指定默認值。
                 5)SPL函數的返回值
                 i)可以使用RETURNING或RETURNS關鍵字定義返回值的返回類型;
                 ii)除了如下兩種數據類型外可以為任何數據類型:
                      Serial/Serial8
                      Text/Byte (可以使用REFERENCES關鍵字傳遞)。
                 iii)在過程體內必須至少有一個return語句;
                 iv)可以為返回值取一個名稱。例如:

          CREATE FUNCTION val_comp (val1 INTEGER, val2 INTEGER)
          RETURNING 
          INTEGER AS comp_res;

                6)SPL的重載
                可定義多個具有相同名字的SPL函數;例如如下SPL函數雖然名稱相同,但是參數類型或各不相同:

          CREATE FUNCTION val_comp (val1 INTEGER, val2 INTEGER)
          CREATE FUNCTION val_comp (val1 CHAR(25), val2 CHAR(25))
          CREATE FUNCTION val_comp (val1 DECIMAL, val2 DECIMAL)

               可使用SPECIFIC關鍵字指定SPL函數的簡短的、獨一無二的被重載的SPL的函數的名稱。這個名字在數據庫中是唯一的。例如:

          CREATE FUNCTION val_comp (val1 INTEGER, val2 INTEGER) SPECIFIC int_comp
          CREATE FUNCTION val_comp (val1 CHAR(25), val2 CHAR(25)) SPECIFIC string_comp
          CREATE FUNCTION val_comp (val1 DECIMAL, val2 DECIMAL) SPECIFIC dec_comp

               7)何謂語句塊?
               i)語句塊是一組SPL或SQL語句;
               ii)隱式的語句塊包含在CREATE PROCEDURE/FUNCTION和END PROCEDURE/FUNCITON之間;
               iii)可使用BEGIN和END來顯式的知名內嵌在另一個語句塊中的語句塊,例如:

          CREATE PROCEDURE myproc1() -- 隱式的語句塊的開始
          DEFINE x INT;
          LET x 
          = 15;
          INSERT INTO table1 VALUES (x, 'amigo');
          BEGIN -- 顯式的語句塊的開始
          DEFINE y INT;
          LET y 
          = 16;
          INSERT INTO table1 VALUES ( y, 'xingxing');
          END -- 顯式的語句塊的結束
          END PROCEDURE-- 隱式的語句塊的結束

                8)如何定義變量?
                i)是語句塊中使用DEFINE定義變量;
                ii)變量在內存中,而不是在數據庫中保存;
                iii)有本地變量和全局變量兩種;
                iv)變量可以是除了如下兩種類型之外的任何一種SQL數據類型和擴展類型:
                       Serial/Serial8
                       Text/Byte (可以使用REFERENCES關鍵字來聲明)。
                定義變量舉例如下:

          DEFINE x, y INT-- 內建的數據類型
          DEFINE p person_type; -- 用戶自定義的數據類型person_type
          DEFINE mymusic REFERENCES BYTE; -- 使用REFERENCES關鍵字定義BYTE類型

                9)本地變量和全局變量比較
                本地變量:
                i)本地變量值在SPL中有效;
                ii)在SPL函數或過程結束后就被復位;
                iii)它不能有默認值;
                iv)它的作用域是在它定義的語句塊中,或者任何內嵌語句塊中;
                v)本地變量能夠被重新定義在另一個語句塊中。
               下面來看一個本地變量的實例:

          CREATE PROCEDURE local_scope()
          DEFINE x,y,z 
          INT;
          LET x 
          = 5;
          LET y 
          = 10;
          LET z 
          = x + y; -- z等于15
          BEGIN
            DEFINE x, q 
          INT-- x被重新定義
            DEFINE z CHAR(5); -- z被重新定義
            LET x = 100;
            LET q 
          = x + y; -- q=110
            LET z = 'amigo'-- 給z設置了一個新的值
          END
          LET y 
          = x; -- y等于5
          LET x = z; -- z的值是15,而不是amigo
             END PROCEDURE;

               全局變量:
               i)在相同數據庫中使用相同的用戶會話的地方都能得到全局變量的值;
               ii)必須有一個默認值;
               iii)必須在每一個要使用它的SPL函數或過程中定義;
               iv)不能是一個集合變量。
               例如如下定義了兩個SPL函數,名稱分別為func1和func2,func1參考語句如下:

          CREATE FUNCTION func1() RETURNING INT;
          DEFINE GLOBAL gvar 
          INT DEFAULT 2;
          LET gvar 
          = gvar + 1;
          RETURN gvar;
          END FUNCTION;

               func2參考語句如下:

          CREATE FUNCTION func2()RETURNING INT;
          DEFINE GLOBAL gvar 
          INT DEFAULT 5;
          LET gvar 
          = gvar + 1;
          RETURN gvar;
          END FUNCTION;

               如果執行兩者的順序如下:

          EXECUTE FUNCTION func1();
          EXECUTE FUNCTION func2();

               則執行完第一句后,gvar被設置了默認值2,且執行了加1的操作,所以第一句執行完畢后gvar的值為3.
               接著執行第二句,第這次不在設置gvar的默認值,因此在3的基礎上再執行了加1操作,執行完畢后gvar的值為4.
               若執行兩者的順序如下:

          EXECUTE FUNCTION func2();
          EXECUTE FUNCTION func1();

               則執行完第一句后,gvar被設置了默認值5,且執行了加1的操作,所以第一句執行完畢后gvar的值為6.
               接著執行第二句,第這次不在設置gvar的默認值,因此在6的基礎上再執行了加1操作,執行完畢后gvar的值為7.
               10)給變量賦值
               i)使用一個未定義的變量將會報錯;
               ii)給已定義的變量賦值的方法:
                     * 使用LET語句直接給變量賦初值,參考語句如下:

                LET <變量> = <有效的表達式或函數名>;

                    *使用SELET INTO語句將查詢到的結果給變量賦值,參考語句如下:

                SELECT … INTO <變量> FROM …;

                    *使用CALL...RETURNING語句將返回結果賦給變量,參考語句如下:

                 CALL … RETURNING <變量>;

                    *使用EXECUTE FUNCTION INTO語句,將返回結果賦給變量,參考語句如下:

                 EXECUTE FUNCTION … INTO <變量>;

          3、語法
           
                1)創建SPL過程

          CREATE PROCEDURE name (parameter list) SPECIFIC specific_name
          … {語句塊}
          END PROCEDURE;

                例如,在下面的實例中創建了一個名為set_status的存儲過程,可傳入myid和mystatus兩個參數,在這個存儲過程中,對item_inventory表進行update操作,id字段滿足myid的記錄將status字段更新為mystatus。參考語句如下:

          CREATE PROCEDURE set_status (myid INTEGER DEFAULT 0, mystatus CHAR(25))
          UPDATE item_inventory SET status = mystatus WHERE id = myid;
          END PROCEDURE;

                 2)創建SPL函數

          CREATE FUNCTION name (parameter list)
          RETURNING list SPECIFIC specific_name
          … {語句塊}
          END FUNCTION;

                例如,創建一個名為val_comp的SPL函數,可傳入val1和val2兩個參數,在該函數中,比較這兩個變量,如果兩者相等,返回0,否則返回1。參考語句如下:

          CREATE FUNCTION val_comp (val1 INTEGER, val2 INTEGER)
          RETURNING 
          INTEGER;
          DEFINE res 
          INTEGER;
          IF (val1 = val2) THEN
          LET res 
          = 0;
          ELSE
          LET res 
          = 1;
          END IF;
          RETURN res;
          END FUNCTION;

           4、SPL中的流程控制
               1)分支語句if...then...else...end if
               參考實例:

          IF ( condition ) THEN
             statements
          ELIF ( condition ) 
          THEN
             statements
             …
          ELSE
             statements
          END IF;
               2)分支語句case
               參考實例:
          CASE ( condition )
             
          WHEN <value1> THEN
                statements
             
          WHEN <value2> THEN
                statements
                …
              
          ELSE
                statements
          END CASE;
               3)循環語句for
               參考語法如下:
          FOR 變量 IN ( 范圍或值 )
               或者使用如下語法:
          FOR 變量=范圍
               舉例如下:
          FOR count = 2 TO 30
          FOR count = 2 TO 30 STEP 2
          FOR count IN ( 2579)
          FOR count IN ( 2 to 8 STEP 212 to 1922)
          FOR name IN ("AMY", "MAX",
          (
          SELECT name FROM customer WHERE customer_num = 100) )
               4)循環語句while
               參考語法如下所示:
          WHILE (條件表達式)
             執行的語句
          END WHILE;
                while中的條件表達式的舉例如下:
          WHILE (count < 20)
          WHILE (status matches "A*")
          WHILE (EXISTS (SELECT name FROM customer WHERE cus_num=100))
          WHILE (status IN ("A", "I", "D"))
                5)循環語句foreach
                i)被用來取多行數據;
                ii)它打開了一個游標;
                iii)游標用來取得當前的行,以便進行行的更新或刪除操作。
                參考實例如下:
          FOREACH SELECT salary INTO ind_sal
          FROM customer
          WHERE location = “UK"
          sum_sal 
          += ind_sal;
          END FOREACH;
          RETRUN sum_sal;
                 6)continue或exit語句
                 都可以被使用在for、foreach和while循環語句中。
                 參考實例如下:
          FOR i = 1 TO 5
             LET j 
          = i;
             
          WHILE (j > 0)
                LET id 
          = foo(j);
                
          IF (id = 5THEN
                   LET j 
          = j – 1;
                   
          CONTINUE WHILE-- 不執行后續的操作,繼續回到while循環接著執行
                END IF;
                LET 
          sum = sum + 5;
                LET j 
          = j – 1;
                
          IF (sum > 500THEN
                   
          EXIT FOR-- 退出for循環
                END IF;
             
          END WHILE;
          END FOR;
          RETURN sum;
          5、異常處理
                1)ON EXCEPTION語句
                ON EXCEPTION語句語句提供了異常的捕獲和處理機制。在IN中指定要捕獲的錯誤,并指定當異常發生時需要執行的動作。在一個語句塊中允許有多個ON EXCEPTION語句。
                ON EXCEPTION語句必須在DEFINE語句之后,并在在任何可執行的語句塊之前。并且它在內嵌的語句塊中也是有效的。它使用SET語句來接收SQL、ISAM錯誤碼和錯誤信息。
                參考實例如下所示:
          CREATE PROCEDURE ex_test()
             DEFINE sql_err 
          INTEGER;
             DEFINE isam_err 
          INTEGER;
             DEFINE err_txt 
          CHAR(200);
             
          ON EXCEPTION IN (-206SET sql_err, isam_err, err_txt
                
          CREATE TABLE tab1 ( col1 INT, col2 INT);
                
          INSERT INTO tab1 VALUES (12);
                
          INSERT INTO tab1 VALUES (23);
             
          END EXCEPTION
             
          INSERT INTO tab1 VALUES (12); --如果tab1不存在時,跳到異常處理
             INSERT INTO tab1 VALUES (23);
          END PROCEDURE;
                 2)WITH RESUME語句
                 該語句在存儲過程發生錯誤時恢復語句。
                 如下實例展示了WITH RESUME的使用,當異常處理完畢后,繼續后續的語句處理。參考語句如下:
          CREATE PROCEDURE ex_test()
          ON EXCEPTION IN (-206)
               
          CREATE TABLE tab1 (col1 INT, col2 INT);
               
          INSERT INTO tab1 VALUES (12);
          END EXCEPTION WITH RESUME;
          INSERT INTO tab1 VALUES (12); -- 如果tab1不存在,跳到異常處理
          INSERT INTO tab1 VALUES (23); -- 異常處理完成后,繼續該句進行處理
          INSERT INTO tab1 VALUES (34);
          END PROCEDURE;
                 3)RAISE EXCEPTION語句
                 i) 該語句用來創建錯誤;
                 ii)它能夠用來指定SQL錯誤、ISAM錯誤和錯誤信息;
                 iii)用該語句創建的錯誤,能夠被ON EXCEPTION捕獲;
                 iv)可以使用指定的錯誤碼-746來表示自定義的錯誤消息。
                 如下實例使用ON EXCEPTION語句指明了當發生錯誤時將錯誤碼、錯誤信息插入到自定義的錯誤表my_error_table,當傳入的參數小于1時,拋出自定義的-746異常,其余情況成功將數據插入到tab1表中,參考語句如下:
          CREATE PROCEDURE ex_test5 (a INT)
             DEFINE sql_err 
          INTEGER;
             DEFINE isam_err 
          INTEGER;
             DEFINE err_txt 
          CHAR(200);
             
          ON EXCEPTION IN (-746SET sql_err, isam_err, err_txt
                
          INSERT INTO my_error_table values (sql_err, isam_err, err_txt);
             
          END EXCEPTION;
             
          IF (a < 1THEN
                RAISE EXCEPTION 
          -7460, "插入值必須大于0";
             
          END IF;
             
          INSERT INTO tab1 VALUES (1, a);
          END PROCEDURE;
          6、執行SPL函數或存儲過程
                  可使用EXECUTE PROCEDURE語句來執行SPL存儲過程,使用EXECUTE FUNCTION來執行SPL函數;
                  參考實例1:
          EXECUTE PROCEDURE foo();
                  參考實例2:
          CREATE FUNCTION func1() RETURNING INT
              DEFINE myvalue 
          INT;
              CALL foo() RETURNING myvalue;
              
          INSERT INTO table1 VALUES (myvalue);
              
          RETURN myvalue;
          END FUNCTION;
                  參考實例3:
          SELECT * FROM table2 WHERE id = get_id("amigo");
                  參考實例4:
          UPDATE table2 SET col2=foo() WHERE id=1;
          7、刪除SPL函數或存儲過程
                  1)使用DROP PROCEDURE來刪除SPL存儲過程;
                  2)使用DROP FUNCTION來刪除SPL函數;
                  3)使用DROP ROUTINE來刪除SPL存儲過程或SPL函數。
                  幾個參考實例如下:
          DROP PROCEDURE foo;
          DROP PROCEDURE foo (INTEGER);
          DROP SPECIFIC PROCEDURE foo_int;
          DROP FUNCTION foo_ret;
          DROP FUNCTION foo_ret (INTEGER);
          DROP SPECIFIC FUNCTION foo_ret_int;
          DROP ROUTINE foo;
          DROP ROUTINE foo_ret;
          posted on 2010-11-05 16:44 阿蜜果 閱讀(11209) 評論(3)  編輯  收藏 所屬分類: database


          FeedBack:
          # re: informix的存儲過程[未登錄]
          2010-12-31 20:37 | dd
          ding  回復  更多評論
            
          # re: informix的存儲過程
          2011-11-23 15:20 | jsp
          ok ,study thanks  回復  更多評論
            
          # re: informix的存儲過程
          2015-04-17 15:46 | sarahs
          study...  回復  更多評論
            
          <2010年11月>
          31123456
          78910111213
          14151617181920
          21222324252627
          2829301234
          567891011

                生活將我們磨圓,是為了讓我們滾得更遠——“圓”來如此。
                我的作品:
                玩轉Axure RP  (2015年12月出版)
                

                Power Designer系統分析與建模實戰  (2015年7月出版)
                
               Struts2+Hibernate3+Spring2   (2010年5月出版)
               

          留言簿(263)

          隨筆分類

          隨筆檔案

          文章分類

          相冊

          關注blog

          積分與排名

          • 積分 - 2296337
          • 排名 - 3

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 屏边| 仪陇县| 麟游县| 刚察县| 阿巴嘎旗| 姜堰市| 西乌珠穆沁旗| 那坡县| 泗阳县| 大渡口区| 金华市| 阳新县| 玉田县| 盘锦市| 南宫市| 西青区| 瓦房店市| 城步| 卓尼县| 武隆县| 崇仁县| 西盟| 临夏市| 宜州市| 微山县| 台东县| 攀枝花市| 五大连池市| 闻喜县| 自贡市| 桃园县| 英德市| 宜兰县| 宁武县| 枣庄市| 荥阳市| 股票| 左云县| 西平县| 上高县| 南岸区|