SQL存儲(chǔ)過(guò)程, since 2021-12-19

(2021.12.19 Sat)
SQL語(yǔ)句需要先編譯再執(zhí)行厘线,存儲(chǔ)過(guò)程(stored procedure)是完成了特定功能的SQL語(yǔ)句集合投放,經(jīng)過(guò)編譯保存在數(shù)據(jù)庫(kù)中。用戶可以通過(guò)名字調(diào)用和執(zhí)行存儲(chǔ)過(guò)程挣磨,并可以傳遞參數(shù)金蜀,和返回?cái)?shù)據(jù)。

存儲(chǔ)過(guò)程是可編程的函數(shù)吃靠,可以簡(jiǎn)單理解為是在數(shù)據(jù)庫(kù)中實(shí)現(xiàn)的面向?qū)ο笾械姆椒ā?/p>

創(chuàng)建存儲(chǔ)過(guò)程

創(chuàng)建過(guò)程偽代碼

CREATE PROCEDURE <procedure_name>([[IN | OUT | INOUT] arg_name arg_type[, arg_name1 arg_type1])
BEGIN
        <SQL_declaration_section>
        <SQL_execution_section>
END

對(duì)于MySQL硫眨,還需要加入DELIMITER關(guān)鍵詞

DELIMITER &&
CREATE PROCEDURE <procedure_name>([[IN | OUT | INOUT] arg_name arg_type[, arg_name1 arg_type1])
BEGIN
        <SQL_declaration_section>
        <SQL_execution_section>
END &&
DELIMITER;

說(shuō)明:

  • procedure_name: 過(guò)程名
  • IN | OUT | OUTIN: 參數(shù)傳遞方式,IN表示調(diào)用者向過(guò)程傳入的參數(shù)巢块,OUT表示過(guò)程返回給調(diào)用者的參數(shù)/結(jié)果礁阁,OUTIN表示向過(guò)程傳遞變量也從過(guò)程返回變量。
  • arg_name & arg_type:傳入或傳出的變量名與類型
  • BEGIN...END:過(guò)程主體
  • declaration_section:主體的聲明變量部分
  • execution_section:函數(shù)執(zhí)行部分代碼

聲明部分

聲明部分的格式如下

DECLARE <var_name> <var_type> [DEFAULT <default_value>];

DECLARE net_pay FLOAT(9,2) DEFAULT 0;
DECLARE id_name INT DEFAULT 0;
DECLARE dt DATETIME DEFAULT '2021-12-19 11:41:30';
DECLARE vv VARCHAR(255) DEFAULT 'This is a stored procedure demo.';

執(zhí)行部分格式

執(zhí)行部分即SQL的指令夕冲。除了常規(guī)的SQL命令氮兵,可使用IF-ELSECASE-WHEN歹鱼,WHILE-DO泣栈,REPEAT-UNTIL-ENDLOOP-END語(yǔ)句弥姻。這些循環(huán)或判斷結(jié)構(gòu)可結(jié)合LEAVE指令用來(lái)結(jié)束結(jié)構(gòu)南片。同時(shí)注意到,BEGIN-END結(jié)構(gòu)可以嵌套庭敦。

BEGIN-END結(jié)構(gòu)可以被貼標(biāo)簽疼进。

<label>: BEGIN
              <sql_statement>;
END <label>;

label_1: BEGIN
           DECLARE var1 int DEFAULT 0;
           SELECT var1;
END label_1;

判斷和循環(huán)語(yǔ)句的格式

WHILE-DO...END-WHILE

DELIMITER //
CREATE PROCEDURE proc1 ()
     BEGIN
          DECLEAR var INT;
          SET var = 7;
          WHILE var < 6 DO
               INSERT INTO specific_table VALUES (var);
               SET var = var + 1;
          END WHILE;
     END;
//
DELIMITER;

REPEAT...UNTIL...END REPEAT,該命令與WHILE不同的是先運(yùn)行秧廉,后檢查運(yùn)行條件伞广。

DELIMITER //
CREATE PROCEDURE proc2 ()
     BEGIN
          DECLEAR var INT;
          SET var = 5;
          REPEAT 
               INSERT INTO specific_table VALUE (var);
               SET var = 6;
               UNTIL var >= 7;
           END REPEAT;
     END;
//
DELIMITER;

LOOP

DELIMITER//
CREATE PROCEDURE proc ()
     BEGIN
          DECLEAR var INT;
          SET var = 4;
          loop_label: LOOP
               INSERT INTO specific_table VALUES (var);
               SET var = var + 1;
               IF var >= 6
                    LEAVE loop_label;
               END IF;
          END LOOP;
     END;
//
DELIMITER

IF-ELSE-THEN語(yǔ)句

DELIMITER //
CREATE PROCEDURE proc (IN para INT)
     BEGIN
          DECLEAR var INT;
          SET var = para + 6;
          IF para > 0 THEN
               INSERT INTO specific_table VALUES (var);
          ELSE
               INSERT INTO specific_table VALUES (var-para);
          END IF;
     END;
//
DELIMITER;

CASE-WHEN-THEN-ELSE語(yǔ)句

DELIMITER //
CREATE PROCEDURE proc4 (IN parameter INT)
     BEGIN
          DECLARE var INT;
          SET var=parameter+1;
          CASE var
          WHEN 0 THEN
               INSERT INTO t VALUES (17);
          WHEN 1 THEN
               INSERT INTO t VALUES (18);
          ELSE
               INSERT INTO t VALUES (19);
          END CASE ;
     END ;
//
DELIMITER ;

ITERATE迭代通過(guò)引用復(fù)合語(yǔ)句的label,來(lái)從新開始復(fù)合語(yǔ)句疼电。

#ITERATE
DELIMITER //
  CREATE PROCEDURE proc()
  BEGIN
    DECLARE v INT;
    SET v=0;
    LOOP_LABLE:LOOP
      IF v=3 THEN
        SET v=v+1;
        ITERATE LOOP_LABLE;
      END IF;
      INSERT INTO t VALUES(v);
      SET v=v+1;
      IF v>=5 THEN
        LEAVE LOOP_LABLE;
      END IF;
    END LOOP;
  END;
  //
DELIMITER ;

變量作用域

分隔符DELIMITER

注意DELIMITER//DELIMITER;兩句嚼锄,MySQL默認(rèn)以";"為分隔 符,如果沒(méi)有聲明分割符蔽豺,編譯器會(huì)把存儲(chǔ)過(guò)程當(dāng)成SQL語(yǔ)句進(jìn)行處理区丑,則存儲(chǔ)過(guò)程的編譯過(guò)程會(huì)報(bào)錯(cuò),所以要事先用DELIMITER關(guān)鍵字聲明當(dāng)前段分隔符修陡,這樣MySQL才會(huì)將";"當(dāng)做存儲(chǔ)過(guò)程中的代碼沧侥,不會(huì)執(zhí)行這些代碼,用完了之后要把分隔符還原魄鸦。

調(diào)用存儲(chǔ)過(guò)程

在mysql console中調(diào)用格式如下

mysql -> CALL proc_name();

如果調(diào)用時(shí)需要傳入?yún)?shù)或傳出參數(shù)宴杀,需要提前聲明,注意在console中變量名前需要加@拾因。
變量賦值部分的格式如下

SET @<var_name> = <var_value>;
or
SELECT <var_value> INTO @<var_name>;

SET @var = 100; // 賦值
SELECT 'this is a test string' INTO @char_var;
SELECT @var; // 選定和返回?cái)?shù)值變量
SELECT @char_var; // 選定和返回字符變量

注意旺罢,在存儲(chǔ)過(guò)程的執(zhí)行部分調(diào)用時(shí)不需要@符號(hào)斯棒,直接使用變量名即可。在mysql console需要有@標(biāo)識(shí)符主经。

mysql -> SET @var = 1;
mysql -> CALL proc_name(@var);

存儲(chǔ)過(guò)程的查詢

SELECT name FROM mysql.proc WHERE db = <db_name>;
SELECT routine_name FROM information_schema.routines WHERE routine_schema = <db_name>;
SHOW PROCEDURE STATUS WHERE db = <db_name>;

#查看存儲(chǔ)過(guò)程詳細(xì)信息
SHOW CREATE PROCEDURE 數(shù)據(jù)庫(kù).存儲(chǔ)過(guò)程名;

存儲(chǔ)過(guò)程的修改和刪除

ALTER PROCEDURE 更改用CREATE PROCEDURE 建立的預(yù)先指定的存儲(chǔ)過(guò)程,其不會(huì)影響相關(guān)存儲(chǔ)過(guò)程或存儲(chǔ)功能庭惜。

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

變量解釋:

  • sp_name參數(shù)表示存儲(chǔ)過(guò)程或函數(shù)的名稱罩驻;
  • characteristic參數(shù)指定存儲(chǔ)函數(shù)的特性。
  • CONTAINS SQL表示子程序包含SQL語(yǔ)句护赊,但不包含讀或?qū)憯?shù)據(jù)的語(yǔ)句惠遏;
  • NO SQL表示子程序中不包含SQL語(yǔ)句;
  • READS SQL DATA表示子程序中包含讀數(shù)據(jù)的語(yǔ)句骏啰;
  • MODIFIES SQL DATA表示子程序中包含寫數(shù)據(jù)的語(yǔ)句节吮。
  • SQL SECURITY { DEFINER | INVOKER }指明誰(shuí)有權(quán)限來(lái)執(zhí)行,* DEFINER表示只有定義者自己才能夠執(zhí)行判耕;INVOKER表示調(diào)用者可以執(zhí)行透绩。
    COMMENT 'string'是注釋信息。

刪除

DROP PROCEDURE [proc_name1[, proc_name2...]];

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末壁熄,一起剝皮案震驚了整個(gè)濱河市帚豪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌草丧,老刑警劉巖狸臣,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異昌执,居然都是意外死亡烛亦,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門懂拾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)煤禽,“玉大人,你說(shuō)我怎么就攤上這事委粉∥厥Γ” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵贾节,是天一觀的道長(zhǎng)汁汗。 經(jīng)常有香客問(wèn)我,道長(zhǎng)栗涂,這世上最難降的妖魔是什么知牌? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮斤程,結(jié)果婚禮上角寸,老公的妹妹穿的比我還像新娘菩混。我一直安慰自己,他們只是感情好扁藕,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布沮峡。 她就那樣靜靜地躺著,像睡著了一般亿柑。 火紅的嫁衣襯著肌膚如雪邢疙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天望薄,我揣著相機(jī)與錄音疟游,去河邊找鬼。 笑死痕支,一個(gè)胖子當(dāng)著我的面吹牛颁虐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播卧须,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼另绩,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了故慈?” 一聲冷哼從身側(cè)響起板熊,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎察绷,沒(méi)想到半個(gè)月后干签,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拆撼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年容劳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片闸度。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡竭贩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出莺禁,到底是詐尸還是另有隱情留量,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布哟冬,位于F島的核電站楼熄,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏浩峡。R本人自食惡果不足惜可岂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望翰灾。 院中可真熱鬧缕粹,春花似錦稚茅、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至绘面,卻和暖如春虹蒋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背飒货。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留峭竣,地道東北人塘辅。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像皆撩,于是被迫代替她去往敵國(guó)和親扣墩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容