乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      mysql存儲(chǔ)過(guò)程與函數(shù)

       惠所勇 2010-06-13
       MySQL 5.1版支持存儲(chǔ)程序和函數(shù)。一個(gè)存儲(chǔ)程序是可以被存儲(chǔ)在服務(wù)器中的一套SQL語(yǔ)句。一旦它被存儲(chǔ)了,客戶端不需要再重新發(fā)布單獨(dú)的語(yǔ)句,而是可以引用存儲(chǔ)程序來(lái)替代。
      MySQL 5.1版支持存儲(chǔ)程序和函數(shù)。一個(gè)存儲(chǔ)程序是可以被存儲(chǔ)在服務(wù)器中的一套SQL語(yǔ)句。一旦它被存儲(chǔ)了,客戶端不需要再重新發(fā)布單獨(dú)的語(yǔ)句,而是可以引用存儲(chǔ)程序來(lái)替代。

      下面一些情況下存儲(chǔ)程序尤其有用:

      ·         當(dāng)用不同語(yǔ)言編寫(xiě)多客戶應(yīng)用程序,或多客戶應(yīng)用程序在不同平臺(tái)上運(yùn)行且需要執(zhí)行相同的數(shù)據(jù)庫(kù)操作之時(shí)。

      ·         安全極為重要之時(shí)。比如,銀行對(duì)所有普通操作使用存儲(chǔ)程序。這提供一個(gè)堅(jiān)固而安全的環(huán)境,程序可以確保每一個(gè)操作都被妥善記入日志。在這樣一個(gè)設(shè)置中,應(yīng)用程序和用戶不可能直接訪問(wèn)數(shù)據(jù)庫(kù)表,但是僅可以執(zhí)行指定的存儲(chǔ)程序。

      儲(chǔ)程序可以提供改良后的性能,因?yàn)橹挥休^少的信息需要在服務(wù)器和客戶算之間傳送。代價(jià)是增加數(shù)據(jù)庫(kù)服務(wù)器系統(tǒng)的負(fù)荷,因?yàn)楦嗟墓ぷ髟诜?wù)器這邊完成,更少的在客戶端(應(yīng)用程序)那邊完成上。如果許多客戶端機(jī)器(比如網(wǎng)頁(yè)服務(wù)器)只由一個(gè)或少數(shù)幾個(gè)數(shù)據(jù)庫(kù)服務(wù)器提供服務(wù),可以考慮一下存儲(chǔ)程序。

      存儲(chǔ)程序也允許你在數(shù)據(jù)庫(kù)服務(wù)器上有函數(shù)庫(kù)。這是一個(gè)被現(xiàn)代應(yīng)用程序語(yǔ)言共享的特征,它允許這樣的內(nèi)部設(shè)計(jì),比如通過(guò)使用類。使用這些客戶端應(yīng)用程序語(yǔ)言特征對(duì)甚至于數(shù)據(jù)庫(kù)使用范圍以外的編程人員都有好處。

      MySQL為存儲(chǔ)程序遵循SQL:2003語(yǔ)法,這個(gè)語(yǔ)法也被用在IBM的DB2數(shù)據(jù)庫(kù)上。

      MySQL對(duì)存儲(chǔ)程序的實(shí)現(xiàn)還在進(jìn)度中。所有本章敘述的語(yǔ)法都被支持,在有限制或擴(kuò)展的地方會(huì)恰當(dāng)?shù)刂赋鰜?lái)。有關(guān)使用存儲(chǔ)程序的限制的更多討論在附錄 I, 特性限制里提到。

      20.4節(jié),“存儲(chǔ)子程序和觸發(fā)程序的二進(jìn)制日志功能”里所說(shuō)的,存儲(chǔ)子程序的二進(jìn)制日志功能已經(jīng)完成。

      20.1. 存儲(chǔ)程序和授權(quán)表

      存儲(chǔ)程序需要在mysql數(shù)據(jù)庫(kù)中有proc表。這個(gè)表在MySQL 5.1安裝過(guò)程中創(chuàng)建。如果你從早期的版本升級(jí)到MySQL 5.1 ,請(qǐng)確定更新你的授權(quán)表以確保proc表的存在。請(qǐng)參閱2.10.2節(jié) “升級(jí)授權(quán)表”

      在MySQL 5.1中,授權(quán)系統(tǒng)如下考慮存儲(chǔ)子程序:

      ·         創(chuàng)建存儲(chǔ)子程序需要CREATE ROUTINE權(quán)限。

      ·         提醒或移除存儲(chǔ)子程序需要ALTER ROUTINE權(quán)限。這個(gè)權(quán)限自動(dòng)授予子程序的創(chuàng)建者。

      ·         執(zhí)行子程序需要EXECUTE權(quán)限。然而,這個(gè)權(quán)限自動(dòng)授予子程序的創(chuàng)建者。同樣,子程序默認(rèn)的SQL SECURITY 特征是DEFINER,它允許用該子程序訪問(wèn)數(shù)據(jù)庫(kù)的用戶與執(zhí)行子程序聯(lián)系到一起。

      20.2. 存儲(chǔ)程序的語(yǔ)法

      存儲(chǔ)程序和函數(shù)是用CREATE PROCEDURE和CREATE FUNCTION語(yǔ)句創(chuàng)建的子程序。一個(gè)子程序要么是一個(gè)程序要么是一個(gè)函數(shù)。使用CALL語(yǔ)句來(lái)調(diào)用程序,程序只能用輸出變量傳回值。就像別其它函數(shù)調(diào)用一樣,函數(shù)可以被從語(yǔ)句外調(diào)用(即通過(guò)引用函數(shù)名),函數(shù)能返回標(biāo)量值。存儲(chǔ)子程序也可以調(diào)用其它存儲(chǔ)子程序。

      在MySQL 5.1中,一個(gè)存儲(chǔ)子程序或函數(shù)與特定的數(shù)據(jù)庫(kù)相聯(lián)系。這里有幾個(gè)意思:

      ·         當(dāng)一個(gè)子程序被調(diào)用時(shí),一個(gè)隱含的USE db_name 被執(zhí)行(當(dāng)子程序終止時(shí)停止執(zhí)行)。存儲(chǔ)子程序內(nèi)的USE語(yǔ)句時(shí)不允許的。

      ·         你可以使用數(shù)據(jù)庫(kù)名限定子程序名。這可以被用來(lái)引用一個(gè)不在當(dāng)前數(shù)據(jù)庫(kù)中的子程序。比如,要引用一個(gè)與test數(shù)據(jù)庫(kù)關(guān)聯(lián)的存儲(chǔ)程序p或函數(shù)f,你可以說(shuō)CALL test.p()或test.f()。

      ·         數(shù)據(jù)庫(kù)移除的時(shí)候,與它關(guān)聯(lián)的所有存儲(chǔ)子程序也都被移除。

      MySQL 支持非常有用的擴(kuò)展,即它允許在存儲(chǔ)程序中使用常規(guī)的SELECT語(yǔ)句(那就是說(shuō),不使用光標(biāo)或局部變量)。這個(gè)一個(gè)查詢的結(jié)果包被簡(jiǎn)單地直接送到客戶端。多SELECT語(yǔ)句生成多個(gè)結(jié)果包,所以客戶端必須使用支持多結(jié)果包的MySQL客戶端庫(kù)。這意味這客戶端必須使用至少MySQL 4.1以來(lái)的近期版本上的客戶端庫(kù)。

      下面一節(jié)描述用來(lái)創(chuàng)建,改變,移除和查詢存儲(chǔ)程序和函數(shù)的語(yǔ)法。

      20.2.1CREATE PROCEDURECREATE FUNCTION

      CREATE PROCEDURE sp_name ([proc_parameter[,...]])
          [characteristic ...] routine_body
       
      CREATE FUNCTION sp_name ([func_parameter[,...]])
          RETURNS type
          [characteristic ...] routine_body
          
          proc_parameter:
          [ IN | OUT | INOUT ] param_name type
          
          func_parameter:
          param_name type
       
      type:
          Any valid MySQL data type
       
      characteristic:
          LANGUAGE SQL
        | [NOT] DETERMINISTIC
        | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
        | SQL SECURITY { DEFINER | INVOKER }
        | COMMENT 'string'
       
      routine_body:
          Valid SQL procedure statement or statements

      這些語(yǔ)句創(chuàng)建存儲(chǔ)子程序。要在MySQL 5.1中創(chuàng)建子程序,必須具有CREATE ROUTINE權(quán)限,并且ALTER ROUTINE和EXECUTE權(quán)限被自動(dòng)授予它的創(chuàng)建者。如果二進(jìn)制日志功能被允許,你也可能需要SUPER權(quán)限,請(qǐng)參閱20.4節(jié),“存儲(chǔ)子程序和觸發(fā)程序的二進(jìn)制日志功能”。

      默認(rèn)地,子程序與當(dāng)前數(shù)據(jù)庫(kù)關(guān)聯(lián)。要明確地把子程序與一個(gè)給定數(shù)據(jù)庫(kù)關(guān)聯(lián)起來(lái),可以在創(chuàng)建子程序的時(shí)候指定其名字為db_name.sp_name。

      如果子程序名和內(nèi)建的SQL函數(shù)名一樣,定義子程序時(shí),你需要在這個(gè)名字和隨后括號(hào)中間插入一個(gè)空格,否則發(fā)生語(yǔ)法錯(cuò)誤。當(dāng)你隨后調(diào)用子程序的時(shí)候也要插入。為此,即使有可能出現(xiàn)這種情況,我們還是建議最好避免給你自己的存儲(chǔ)子程序取與存在的SQL函數(shù)一樣的名字。

      由括號(hào)包圍的參數(shù)列必須總是存在。如果沒(méi)有參數(shù),也該使用一個(gè)空參數(shù)列()。每個(gè)參數(shù)默認(rèn)都是一個(gè)IN參數(shù)。要指定為其它參數(shù),可在參數(shù)名之前使用關(guān)鍵詞 OUT或INOUT

      注意: 指定參數(shù)為IN, OUT, 或INOUT 只對(duì)PROCEDURE是合法的。(FUNCTION參數(shù)總是被認(rèn)為是IN參數(shù))

      RETURNS字句只能對(duì)FUNCTION指定,對(duì)函數(shù)而言這是強(qiáng)制的。它用來(lái)指定函數(shù)的返回類型,而且函數(shù)體必須包含一個(gè)RETURN value語(yǔ)句。

      routine_body 包含合法的SQL過(guò)程語(yǔ)句。可以使用復(fù)合語(yǔ)句語(yǔ)法,請(qǐng)參閱20.2.7節(jié),“BEGIN ... END復(fù)合語(yǔ)句。復(fù)合語(yǔ)句可以包含聲明,循環(huán)和其它控制結(jié)構(gòu)語(yǔ)句。這些語(yǔ)句的語(yǔ)法在本章后免介紹,舉例,請(qǐng)參閱20.2.8節(jié),“DECLARE語(yǔ)句20.2.12節(jié),“流程控制構(gòu)造”。

      CREATE FUNCTION語(yǔ)句被用在更早的MySQL版本上支持UDF (自定義函數(shù))。請(qǐng)參閱27.2節(jié),“給MySQL添加新函數(shù)”。 UDF繼續(xù)被支持,即使現(xiàn)在有了存儲(chǔ)函數(shù)。UDF會(huì)被認(rèn)為一個(gè)外部存儲(chǔ)函數(shù)。然而,不要讓存儲(chǔ)函數(shù)與UDF函數(shù)共享名字空間。

      外部存儲(chǔ)程序的框架將在不久的將來(lái)引入。這將允許你用SQL之外的語(yǔ)言編寫(xiě)存儲(chǔ)程序。最可能的是,第一個(gè)被支持語(yǔ)言是PHP,因?yàn)楹诵腜HP引擎很小,線程安全,且可以被方便地嵌入。因?yàn)榭蚣苁枪_(kāi)的,它希望許多其它語(yǔ)言也能被支持。

      如果程序或線程總是對(duì)同樣的輸入?yún)?shù)產(chǎn)生同樣的結(jié)果,則被認(rèn)為它是“確定的”,否則就是“非確定”的。如果既沒(méi)有給定DETERMINISTIC也沒(méi)有給定NOT DETERMINISTIC,默認(rèn)的就是NOT DETERMINISTIC。

      為進(jìn)行復(fù)制,使用NOW()函數(shù)(或它的同義詞)或RAND()函數(shù)會(huì)不必要地使得一個(gè)子程序非確定。對(duì)NOW()而言,二進(jìn)制日志包括時(shí)間戳并被正確復(fù)制。RAND() 只要在一個(gè)子程序被內(nèi)應(yīng)用一次也會(huì)被正確復(fù)制。(你可以把子程序執(zhí)行時(shí)間戳和隨機(jī)數(shù)種子認(rèn)為強(qiáng)制輸入,它們?cè)谥鲝纳鲜峭瑯拥摹#?

      當(dāng)前來(lái)講,DETERMINISTIC特征被接受,但還沒(méi)有被優(yōu)化程序所使用。然而如果二進(jìn)制日志功能被允許了,這個(gè)特征影響到MySQL是否會(huì)接受子程序定義。請(qǐng)參閱20.4節(jié),“存儲(chǔ)子程序和觸發(fā)程序的二進(jìn)制日志功能”

      一些特征提供子程序使用數(shù)據(jù)的內(nèi)在信息。CONTAINS SQL表示子程序不包含讀或?qū)憯?shù)據(jù)的語(yǔ)句。NO SQL表示子程序不包含SQL語(yǔ)句。READS SQL DATA表示子程序包含讀數(shù)據(jù)的語(yǔ)句,但不包含寫(xiě)數(shù)據(jù)的語(yǔ)句。MODIFIES SQL DATA表示子程序包含寫(xiě)數(shù)據(jù)的語(yǔ)句。如果這些特征沒(méi)有明確給定,默認(rèn)的是CONTAINS SQL。

      SQL SECURITY特征可以用來(lái)指定 子程序該用創(chuàng)建子程序者的許可來(lái)執(zhí)行,還是使用調(diào)用者的許可來(lái)執(zhí)行。默認(rèn)值是DEFINER。在SQL:2003中者是一個(gè)新特性。創(chuàng)建者或調(diào)用者必須由訪問(wèn)子程序關(guān)聯(lián)的數(shù)據(jù)庫(kù)的許可。在MySQL 5.1中,必須有EXECUTE權(quán)限才能執(zhí)行子程序。必須擁有這個(gè)權(quán)限的用戶要么是定義者,要么是調(diào)用者,這取決于SQL SECURITY特征是如何設(shè)置的。

      MySQL存儲(chǔ)sql_mode系統(tǒng)變量設(shè)置,這個(gè)設(shè)置在子程序被創(chuàng)建的時(shí)候起作用,MySQL總是強(qiáng)制使用這個(gè)設(shè)置來(lái)執(zhí)行子程序。

      COMMENT子句是一個(gè)MySQL的擴(kuò)展,它可以被用來(lái)描述存儲(chǔ)程序。這個(gè)信息被SHOW CREATE PROCEDURE和 SHOW CREATE FUNCTION語(yǔ)句來(lái)顯示。

      MySQL允許子程序包含DDL語(yǔ)句,如CREATE和DROP。MySQL也允許存儲(chǔ)程序(但不是存儲(chǔ)函數(shù))包含SQL 交互語(yǔ)句,如COMMIT。存儲(chǔ)函數(shù)不可以包含那些做明確的和絕對(duì)的提交或者做回滾的語(yǔ)。SQL標(biāo)準(zhǔn)不要求對(duì)這些語(yǔ)句的支持,SQL標(biāo)準(zhǔn)聲明每個(gè)DBMS提供商可以決定是否允許支持這些語(yǔ)句。

      存儲(chǔ)子程序不能使用LOAD DATA INFILE。

      返回結(jié)果包的語(yǔ)句不能被用在存儲(chǔ)函數(shù)種。這包括不使用INTO給變量讀取列值的SELECT語(yǔ)句,SHOW 語(yǔ)句,及其它諸如EXPLAIN這樣的語(yǔ)句。對(duì)于可在函數(shù)定義時(shí)間被決定要返回一個(gè)結(jié)果包的語(yǔ)句,發(fā)生一個(gè)允許從函數(shù)錯(cuò)誤返回結(jié)果包的Not(ER_SP_NO_RETSET_IN_FUNC)。對(duì)于只可在運(yùn)行時(shí)決定要返回一個(gè)結(jié)果包的語(yǔ)句, 發(fā)生一個(gè)不能在給定上下文錯(cuò)誤返回結(jié)果包的PROCEDURE %s (ER_SP_BADSELECT)。

      下面是一個(gè)使用OUT參數(shù)的簡(jiǎn)單的存儲(chǔ)程序的例子。例子為,在程序被定義的時(shí)候,用mysql客戶端delimiter命令來(lái)把語(yǔ)句定界符從 ;變?yōu)?/。這就允許用在程序體中的;定界符被傳遞到服務(wù)器而不是被mysql自己來(lái)解釋。

      mysql> delimiter //
       
      mysql> CREATE PROCEDURE simpleproc (OUT param1 INT)
          -> BEGIN
          ->   SELECT COUNT(*) INTO param1 FROM t;
          -> END
          -> //
      Query OK, 0 rows affected (0.00 sec)
       
      mysql> delimiter ;
       
      mysql> CALL simpleproc(@a);
      Query OK, 0 rows affected (0.00 sec)
       
      mysql> SELECT @a;
      +------+
      | @a   |
      +------+
      | 3    |
      +------+
      1 row in set (0.00 sec)

      當(dāng)使用delimiter命令時(shí),你應(yīng)該避免使用反斜杠(\)字符,因?yàn)槟鞘荕ySQL的轉(zhuǎn)義字符。

      下列是一個(gè)例子,一個(gè)采用參數(shù)的函數(shù)使用一個(gè)SQL函數(shù)執(zhí)行一個(gè)操作,并返回結(jié)果:

      mysql> delimiter //
       
      mysql> CREATE FUNCTION hello (s CHAR(20)) RETURNS CHAR(50)
          -> RETURN CONCAT('Hello, ',s,'!');
          -> //
      Query OK, 0 rows affected (0.00 sec)
       
      mysql> delimiter ;
       
      mysql> SELECT hello('world');
      +----------------+
      | hello('world') |
      +----------------+
      | Hello, world!  |
      +----------------+
      1 row in set (0.00 sec)

      如果在存儲(chǔ)函數(shù)中的RETURN語(yǔ)句返回一個(gè)類型不同于在函數(shù)的RETURNS子句中指定類型的值,返回值被強(qiáng)制為恰當(dāng)?shù)念愋?。比如,如果一個(gè)函數(shù)返回一個(gè)ENUM或SET值,但是RETURN語(yǔ)句返回一個(gè)整數(shù),對(duì)于SET成員集的相應(yīng)的ENUM成員,從函數(shù)返回的值是字符串。

      20.2.2. ALTER PROCEDUREALTER FUNCTION

      ALTER {PROCEDURE | FUNCTION} sp_name [characteristic ...]
       
      characteristic:
          { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
        | SQL SECURITY { DEFINER | INVOKER }
        | COMMENT 'string'

      這個(gè)語(yǔ)句可以被用來(lái)改變一個(gè)存儲(chǔ)程序或函數(shù)的特征。在MySQL 5.1中,你必須用ALTER ROUTINE權(quán)限才可用此子程序。這個(gè)權(quán)限被自動(dòng)授予子程序的創(chuàng)建者。如20.4節(jié),“存儲(chǔ)子程序和觸發(fā)程序的二進(jìn)制日志功能”中所述, 如果二進(jìn)制日志功能被允許了,你可能也需要SUPER權(quán)限。

      在ALTER PROCEDURE和ALTER FUNCTION語(yǔ)句中,可以指定超過(guò)一個(gè)的改變。

      20.2.3. DROP PROCEDUREDROP FUNCTION

      DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name

      這個(gè)語(yǔ)句被用來(lái)移除一個(gè)存儲(chǔ)程序或函數(shù)。即,從服務(wù)器移除一個(gè)制定的子程序。在MySQL 5.1中,你必須有ALTER ROUTINE權(quán)限才可用此子程序。這個(gè)權(quán)限被自動(dòng)授予子程序的創(chuàng)建者。

      IF EXISTS 子句是一個(gè)MySQL的擴(kuò)展。如果程序或函數(shù)不存儲(chǔ),它防止發(fā)生錯(cuò)誤。產(chǎn)生一個(gè)可以用SHOW WARNINGS查看的警告。

      20.2.4. SHOW CREATE PROCEDURESHOW CREATE FUNCTION

      SHOW CREATE {PROCEDURE | FUNCTION} sp_name

      這個(gè)語(yǔ)句是一個(gè)MySQL的擴(kuò)展。類似于SHOW CREATE TABLE,它返回一個(gè)可用來(lái)重新創(chuàng)建已命名子程序的確切字符串。

      mysql> SHOW CREATE FUNCTION test.hello\G
      *************************** 1. row ***************************
             Function: hello
             sql_mode:
      Create Function: CREATE FUNCTION `test`.`hello`(s CHAR(20)) RETURNS CHAR(50)
      RETURN CONCAT('Hello, ',s,'!')

      20.2.5. SHOW PROCEDURE STATUSSHOW FUNCTION STATUS

      SHOW {PROCEDURE | FUNCTION} STATUS [LIKE 'pattern']

      這個(gè)語(yǔ)句是一個(gè)MySQL的擴(kuò)展。它返回子程序的特征,如數(shù)據(jù)庫(kù),名字,類型,創(chuàng)建者及創(chuàng)建和修改日期。如果沒(méi)有指定樣式,根據(jù)你使用的語(yǔ)句,所有存儲(chǔ)程序和所有存儲(chǔ)函數(shù)的信息都被列出。

      mysql> SHOW FUNCTION STATUS LIKE 'hello'\G
      *************************** 1. row ***************************
                 Db: test
               Name: hello
               Type: FUNCTION
            Definer: testuser@localhost
           Modified: 2004-08-03 15:29:37
            Created: 2004-08-03 15:29:37
      Security_type: DEFINER
            Comment:

      你可以從INFORMATION_SCHEMA中的ROUTINES表獲得有關(guān)存儲(chǔ)子程序的信息。請(qǐng)參閱23.1.14節(jié),“INFORMATION_SCHEMA ROUTINES 表。

      20.2.6. CALL語(yǔ)句

      CALL sp_name([parameter[,...]])

      CALL語(yǔ)句調(diào)用一個(gè)先前用CREATE PROCEDURE創(chuàng)建的程序。

      CALL語(yǔ)句可以用聲明為OUT或的INOUT參數(shù)的參數(shù)給它的調(diào)用者傳回值。它也“返回”受影響的行數(shù),客戶端程序可以在SQL級(jí)別通過(guò)調(diào)用ROW_COUNT()函數(shù)獲得這個(gè)數(shù),從C中是調(diào)用the mysql_affected_rows() C API函數(shù)來(lái)獲得。

      20.2.7. BEGIN ... END復(fù)合語(yǔ)句

      [begin_label:] BEGIN
          [statement_list]
      END [end_label]

      存儲(chǔ)子程序可以使用BEGIN ... END復(fù)合語(yǔ)句來(lái)包含多個(gè)語(yǔ)句。statement_list 代表一個(gè)或多個(gè)語(yǔ)句的列表。statement_list之內(nèi)每個(gè)語(yǔ)句都必須用分號(hào)(;)來(lái)結(jié)尾。

      復(fù)合語(yǔ)句可以被標(biāo)記。除非begin_label存在,否則end_label不能被給出,并且如果二者都存在,他們必須是同樣的。

      請(qǐng)注意,可選的[NOT] ATOMIC子句現(xiàn)在還不被支持。這意味著在指令塊的開(kāi)始沒(méi)有交互的存儲(chǔ)點(diǎn)被設(shè)置,并且在上下文中用到的BEGIN子句對(duì)當(dāng)前交互動(dòng)作沒(méi)有影響。

      使用多重語(yǔ)句需要客戶端能發(fā)送包含語(yǔ)句定界符;的查詢字符串。這個(gè)符號(hào)在命令行客戶端被用delimiter命令來(lái)處理。改變查詢結(jié)尾定界符;(比如改變?yōu)?/)使得; 可被用在子程序體中。

      20.2.8. DECLARE語(yǔ)句

      DECLARE語(yǔ)句被用來(lái)把不同項(xiàng)目局域到一個(gè)子程序:局部變量(請(qǐng)參閱20.2.9節(jié),“存儲(chǔ)程序中的變量”),條件和處理程序(請(qǐng)參閱20.2.10節(jié),“條件和處理程序”) 及光標(biāo)(請(qǐng)參閱20.2.11節(jié),“光標(biāo)”)。SIGNAL和RESIGNAL語(yǔ)句當(dāng)前還不被支持。

      DECLARE僅被用在BEGIN ... END復(fù)合語(yǔ)句里,并且必須在復(fù)合語(yǔ)句的開(kāi)頭,在任何其它語(yǔ)句之前。

      光標(biāo)必須在聲明處理程序之前被聲明,并且變量和條件必須在聲明光標(biāo)或處理程序之前被聲明。

      20.2.9. 存儲(chǔ)程序中的變量

      你可以在子程序中聲明并使用變量。

      20.2.9.1. DECLARE局部變量

      DECLARE var_name[,...] type [DEFAULT value]

      這個(gè)語(yǔ)句被用來(lái)聲明局部變量。要給變量提供一個(gè)默認(rèn)值,請(qǐng)包含一個(gè)DEFAULT子句。值可以被指定為一個(gè)表達(dá)式,不需要為一個(gè)常數(shù)。如果沒(méi)有DEFAULT子句,初始值為NULL。

      局部變量的作用范圍在它被聲明的BEGIN ... END塊內(nèi)。它可以被用在嵌套的塊中,除了那些用相同名字聲明變量的塊。

      20.2.9.2. 變量SET語(yǔ)句

      SET var_name = expr [, var_name = expr] ...

      在存儲(chǔ)程序中的SET語(yǔ)句是一般SET語(yǔ)句的擴(kuò)展版本。被參考變量可能是子程序內(nèi)聲明的變量,或者是全局服務(wù)器變量。

      在存儲(chǔ)程序中的SET語(yǔ)句作為預(yù)先存在的SET語(yǔ)法的一部分來(lái)實(shí)現(xiàn)。這允許SET a=x, b=y, ...這樣的擴(kuò)展語(yǔ)法。其中不同的變量類型(局域聲明變量及全局和集體變量)可以被混合起來(lái)。這也允許把局部變量和一些只對(duì)系統(tǒng)變量有意義的選項(xiàng)合并起來(lái)。在那種情況下,此選項(xiàng)被識(shí)別,但是被忽略了。

      20.2.9.3. SELECT ... INTO語(yǔ)句

      SELECT col_name[,...] INTO var_name[,...] table_expr

      這個(gè)SELECT語(yǔ)法把選定的列直接存儲(chǔ)到變量。因此,只有單一的行可以被取回。

      SELECT id,data INTO x,y FROM test.t1 LIMIT 1;

      注意,用戶變量名在MySQL 5.1中是對(duì)大小寫(xiě)不敏感的。請(qǐng)參閱9.3節(jié),“用戶變量”

      重要: SQL變量名不能和列名一樣。如果SELECT ... INTO這樣的SQL語(yǔ)句包含一個(gè)對(duì)列的參考,并包含一個(gè)與列相同名字的局部變量,MySQL當(dāng)前把參考解釋為一個(gè)變量的名字。例如,在下面的語(yǔ)句中,xname 被解釋為到xname variable 的參考而不是到xname column的:

      CREATE PROCEDURE sp1 (x VARCHAR(5))
        BEGIN
          DECLARE xname VARCHAR(5) DEFAULT 'bob';
          DECLARE newname VARCHAR(5);
          DECLARE xid INT;
          
          SELECT xname,id INTO newname,xid 
            FROM table1 WHERE xname = xname;
          SELECT newname;
        END;

      當(dāng)這個(gè)程序被調(diào)用的時(shí)候,無(wú)論table.xname列的值是什么,變量newname將返回值‘bob’。

      請(qǐng)參閱I.1節(jié),“存儲(chǔ)子程序和觸發(fā)程序的限制”。

      20.2.10. 條件和處理程序

      特定條件需要特定處理。這些條件可以聯(lián)系到錯(cuò)誤,以及子程序中的一般流程控制。

      20.2.10.1. DECLARE條件

      DECLARE condition_name CONDITION FOR condition_value
       
      condition_value:
          SQLSTATE [VALUE] sqlstate_value
        | mysql_error_code

      這個(gè)語(yǔ)句指定需要特殊處理的條件。它將一個(gè)名字和指定的錯(cuò)誤條件關(guān)聯(lián)起來(lái)。這個(gè)名字可以隨后被用在DECLARE HANDLER語(yǔ)句中。請(qǐng)參閱20.2.10.2節(jié),“DECLARE處理程序。

      除了SQLSTATE值,也支持MySQL錯(cuò)誤代碼。

      20.2.10.2. DECLARE處理程序

      DECLARE handler_type HANDLER FOR condition_value[,...] sp_statement
       
      handler_type:
          CONTINUE
        | EXIT
        | UNDO
       
      condition_value:
          SQLSTATE [VALUE] sqlstate_value
        | condition_name
        | SQLWARNING
        | NOT FOUND
        | SQLEXCEPTION
        | mysql_error_code

      這個(gè)語(yǔ)句指定每個(gè)可以處理一個(gè)或多個(gè)條件的處理程序。如果產(chǎn)生一個(gè)或多個(gè)條件,指定的語(yǔ)句被執(zhí)行。

      對(duì)一個(gè)CONTINUE處理程序,當(dāng)前子程序的執(zhí)行在執(zhí)行處理程序語(yǔ)句之后繼續(xù)。對(duì)于EXIT處理程序,當(dāng)前BEGIN...END復(fù)合語(yǔ)句的執(zhí)行被終止。UNDO 處理程序類型語(yǔ)句還不被支持。

      ·         SQLWARNING是對(duì)所有以01開(kāi)頭的SQLSTATE代碼的速記。

      ·         NOT FOUND是對(duì)所有以02開(kāi)頭的SQLSTATE代碼的速記。

      ·         SQLEXCEPTION是對(duì)所有沒(méi)有被SQLWARNING或NOT FOUND捕獲的SQLSTATE代碼的速記。

      除了SQLSTATE值,MySQL錯(cuò)誤代碼也不被支持。

      例如:

      mysql> CREATE TABLE test.t (s1 int,primary key (s1));
      Query OK, 0 rows affected (0.00 sec)
       
      mysql> delimiter //
       
      mysql> CREATE PROCEDURE handlerdemo ()
          -> BEGIN
          ->   DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1;
          ->   SET @x = 1;
          ->   INSERT INTO test.t VALUES (1);
          ->   SET @x = 2;
          ->   INSERT INTO test.t VALUES (1);
          ->   SET @x = 3;
          -> END;
          -> //
      Query OK, 0 rows affected (0.00 sec)
       
      mysql> CALL handlerdemo()//
      Query OK, 0 rows affected (0.00 sec)
       
      mysql> SELECT @x//
          +------+
          | @x   |
          +------+
          | 3    |
          +------+
          1 row in set (0.00 sec)

      注意到,@x是3,這表明MySQL被執(zhí)行到程序的末尾。如果DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1; 這一行不在,第二個(gè)INSERT因PRIMARY KEY強(qiáng)制而失敗之后,MySQL可能已經(jīng)采取默認(rèn)(EXIT)路徑,并且SELECT @x可能已經(jīng)返回2。

      20.2.11. 光標(biāo)

      簡(jiǎn)單光標(biāo)在存儲(chǔ)程序和函數(shù)內(nèi)被支持。語(yǔ)法如同在嵌入的SQL中。光標(biāo)當(dāng)前是不敏感的,只讀的及不滾動(dòng)的。不敏感意為服務(wù)器可以活不可以復(fù)制它的結(jié)果表。

      光標(biāo)必須在聲明處理程序之前被聲明,并且變量和條件必須在聲明光標(biāo)或處理程序之前被聲明。

      例如:

      CREATE PROCEDURE curdemo()
      BEGIN
        DECLARE done INT DEFAULT 0;
        DECLARE a CHAR(16);
        DECLARE b,c INT;
        DECLARE cur1 CURSOR FOR select id,data FROM test.t1;
        DECLARE cur2 CURSOR FOR select i FROM test.t2;
        DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
       
        OPEN cur1;
        OPEN cur2;
       
        REPEAT
          FETCH cur1 INTO a, b;
          FETCH cur2 INTO c;
          IF NOT done THEN
             IF b < c THEN
                INSERT INTO test.t3 VALUES (a,b);
             ELSE
                INSERT INTO test.t3 VALUES (a,c);
             END IF;
          END IF;
        UNTIL done END REPEAT;
       
        CLOSE cur1;
        CLOSE cur2;
      END

      20.2.11.1.聲明光標(biāo)

      DECLARE cursor_name CURSOR FOR select_statement

      這個(gè)語(yǔ)句聲明一個(gè)光標(biāo)。也可以在子程序中定義多個(gè)光標(biāo),但是一個(gè)塊中的每一個(gè)光標(biāo)必須有唯一的名字。

      SELECT語(yǔ)句不能有INTO子句。

      20.2.11.2. 光標(biāo)OPEN語(yǔ)句

      OPEN cursor_name

      這個(gè)語(yǔ)句打開(kāi)先前聲明的光標(biāo)。

      20.2.11.3. 光標(biāo)FETCH語(yǔ)句

      FETCH cursor_name INTO var_name [, var_name] ...

      這個(gè)語(yǔ)句用指定的打開(kāi)光標(biāo)讀取下一行(如果有下一行的話),并且前進(jìn)光標(biāo)指針。

      20.2.11.4. 光標(biāo)CLOSE語(yǔ)句

      CLOSE cursor_name

      這個(gè)語(yǔ)句關(guān)閉先前打開(kāi)的光標(biāo)。

      如果未被明確地關(guān)閉,光標(biāo)在它被聲明的復(fù)合語(yǔ)句的末尾被關(guān)閉。

      20.2.12. 流程控制構(gòu)造

      IF, CASE, LOOP, WHILE, ITERATE, 及 LEAVE 構(gòu)造被完全實(shí)現(xiàn)。

      這些構(gòu)造可能每個(gè)包含要么一個(gè)單獨(dú)語(yǔ)句,要么是使用BEGIN ... END復(fù)合語(yǔ)句的一塊語(yǔ)句。構(gòu)造可以被嵌套。

      目前還不支持FOR循環(huán)。

      20.2.12.1. IF語(yǔ)句

      IF search_condition THEN statement_list
          [ELSEIF search_condition THEN statement_list] ...
          [ELSE statement_list]
      END IF

      IF實(shí)現(xiàn)了一個(gè)基本的條件構(gòu)造。如果search_condition求值為真,相應(yīng)的SQL語(yǔ)句列表被執(zhí)行。如果沒(méi)有search_condition匹配,在ELSE子句里的語(yǔ)句列表被執(zhí)行。statement_list可以包括一個(gè)或多個(gè)語(yǔ)句。

      請(qǐng)注意,也有一個(gè)IF() 函數(shù),它不同于這里描述的IF語(yǔ)句。請(qǐng)參閱12.2節(jié),“控制流程函數(shù)”。

      20.2.12.2. CASE語(yǔ)句

      CASE case_value
          WHEN when_value THEN statement_list
          [WHEN when_value THEN statement_list] ...
          [ELSE statement_list]
      END CASE

      Or:

      CASE
          WHEN search_condition THEN statement_list
          [WHEN search_condition THEN statement_list] ...
          [ELSE statement_list]
      END CASE

      存儲(chǔ)程序的CASE語(yǔ)句實(shí)現(xiàn)一個(gè)復(fù)雜的條件構(gòu)造。如果search_condition 求值為真,相應(yīng)的SQL被執(zhí)行。如果沒(méi)有搜索條件匹配,在ELSE子句里的語(yǔ)句被執(zhí)行。

      注意:這里介紹的用在存儲(chǔ)程序里的CASE語(yǔ)句與12.2節(jié),“控制流程函數(shù)”里描述的SQL CASE表達(dá)式的CASE語(yǔ)句有輕微不同。這里的CASE語(yǔ)句不能有ELSE NULL子句,并且用END CASE替代END來(lái)終止。

      20.2.12.3. LOOP語(yǔ)句

      [begin_label:] LOOP
          statement_list
      END LOOP [end_label]

      LOOP允許某特定語(yǔ)句或語(yǔ)句群的重復(fù)執(zhí)行,實(shí)現(xiàn)一個(gè)簡(jiǎn)單的循環(huán)構(gòu)造。在循環(huán)內(nèi)的語(yǔ)句一直重復(fù)直循環(huán)被退出,退出通常伴隨著一個(gè)LEAVE 語(yǔ)句。

      LOOP語(yǔ)句可以被標(biāo)注。除非begin_label存在,否則end_label不能被給出,并且如果兩者都出現(xiàn),它們必須是同樣的。

      20.2.12.4. LEAVE語(yǔ)句

      LEAVE label

      這個(gè)語(yǔ)句被用來(lái)退出任何被標(biāo)注的流程控制構(gòu)造。它和BEGIN ... END或循環(huán)一起被使用。

      20.2.12.5. ITERATE語(yǔ)句

      ITERATE label

      ITERATE只可以出現(xiàn)在LOOP, REPEAT, 和WHILE語(yǔ)句內(nèi)。ITERATE意思為:“再次循環(huán)。”

      例如:

      CREATE PROCEDURE doiterate(p1 INT)
      BEGIN
        label1: LOOP
          SET p1 = p1 + 1;
          IF p1 < 10 THEN ITERATE label1; END IF;
          LEAVE label1;
        END LOOP label1;
        SET @x = p1;
      END

      20.2.12.6. REPEAT語(yǔ)句

      [begin_label:] REPEAT
          statement_list
      UNTIL search_condition
      END REPEAT [end_label]

      REPEAT語(yǔ)句內(nèi)的語(yǔ)句或語(yǔ)句群被重復(fù),直至search_condition 為真。

      REPEAT 語(yǔ)句可以被標(biāo)注。 除非begin_label也存在,end_label才能被用,如果兩者都存在,它們必須是一樣的。

      例如

      mysql> delimiter //
       
      mysql> CREATE PROCEDURE dorepeat(p1 INT)
          -> BEGIN
          ->   SET @x = 0;
          ->   REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT;
          -> END
          -> //
      Query OK, 0 rows affected (0.00 sec)
       
      mysql> CALL dorepeat(1000)//
      Query OK, 0 rows affected (0.00 sec)
       
      mysql> SELECT @x//
      +------+
      | @x   |
      +------+
      | 1001 |
      +------+
      1 row in set (0.00 sec)

      20.2.12.7. WHILE語(yǔ)句

      [begin_label:] WHILE search_condition DO
          statement_list
      END WHILE [end_label]

      WHILE語(yǔ)句內(nèi)的語(yǔ)句或語(yǔ)句群被重復(fù),直至search_condition 為真。

      WHILE語(yǔ)句可以被標(biāo)注。 除非begin_label也存在,end_label才能被用,如果兩者都存在,它們必須是一樣的。

      例如:

      CREATE PROCEDURE dowhile()
      BEGIN
        DECLARE v1 INT DEFAULT 5;
       
        WHILE v1 > 0 DO
          ...
          SET v1 = v1 - 1;
        END WHILE;
      END

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多