91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么理解MySQL存儲過程和觸發器

發布時間:2021-11-20 09:53:23 來源:億速云 閱讀:116 作者:柒染 欄目:MySQL數據庫

這期內容當中小編將會給大家帶來有關怎么理解MySQL存儲過程和觸發器,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

存儲過程(stored procedure SP)是MySQL 5.0 版本中的最大創新。他們是一些由MySQL服務器直接存儲和執行的定制過程 或 函數。SP的加入把SQL語言擴展成了一種程序設計語言,可以利用SP把一個客戶--服務器體系的數據庫應用軟件中的部分邏輯保存起來供日后使用。

觸發器(trigger) 是在INSERT ,UPDATE 或 DELETE 命令之前或者之后對SQL命令或SP的自動自動調用。

----------------------------------------
//輸入都必須以 '$$'作為結束符號
delimiter $$

我們先來創建一個最簡單的函數,
函數的功能是寫入兩個數,得出 和:

Create FUNCTION addition(v1 int(11),v2 int(11))
RETURNS int(11)
BEGIN

return (v1+v2);

END$$


//把結束符號換回來
delimiter ;


讓我們來調用我們的函數:
select addition(11,15) ;  結果 26 正確。


讓我們來查看一下數據庫中有那些函數
show function status;

如何來查看addition的代碼?
show create function addition;


現在讓我們來刪除那個函數:
drop function addition;


----------------------------------------


上面是小試牛刀。 現在開始我們來全面學習MYSQL中的存儲過程 和 觸發器


分3個類 FUNCTION , PROCEDURE ,TRIGGER 來學習研究。

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
                                             FUNCTION
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

語法 :

CREATE FUNCTION function_name (param1 datatype [,param2 datatype ,.....])
RETURNS datatype

BEGIN
commands;
END


---------------------------------------------------------------------------

SP 注釋

"--" 開始并且一直到這一行的結尾都是注釋

------------------------------------------


(1)FUNCTION 中的局部變量的定義 和 變量的賦值

* 變量的定義
語法 :
DECLARE varname1 datatype1 [DEFAULT value];
DECLARE varname1,varname2 .... datatype [DEFAULT value]; //多變量同類型的定義方式

$ 變量的定義要在BEGIN ... END  之間定義。
$ 如果在FUNCTION 體中定義了多個BEGIN ... END 嵌套,那么 變量的定義只能在當前 BEGIN .. END 或則 子 BEGIN ... END 中有效。
$ 子類 BEGIN ... END 中的變量定義可以覆蓋父類 BEGIN ... END 中定義的變量。

* 對變量的賦值
對變量的賦值有兩種方法。

[1]直接給變量賦給常量,或則把其他的變量賦值給當前變量
  set var = value;
 set var1 = value1,var2 = value2....;

[2]把SQL查詢結果賦值給變量
 SELECT var := value  //一種以SELECT 方法 把常量或其他變量賦值給當前變量的方法
 SELECT nomalvalue INTO var  //又一種以SELECT 方法 把常量或其他變量賦值給當前變量的方法
 SELECT value FROM TABLE .. INTO var;
 SELECT value1,value2 FROM TABLE .. INTO var1,var2;


SELECT INTO 命令是SELECT 命令的一種變體。 它上一以 INTO varname 結束整條命令。
要求,SELECT命令返回并且只能返回一條記錄。(不允許多條記錄)


example-001:

use wyd

delimiter $$

----------------------
create table person(
id int primary key auto_increment,
age int
) $$

----------------------
insert into person(age)values(12);
insert into person(age)values(34);
insert into person(age)values(42);
insert into person(age)values(13);
insert into person(age)values(2)$$

-----------------------
drop function addtion$$

----------------------

CREATE FUNCTION getage(person_id int)
RETURNS int
BEGIN
DECLARE person_age int default 0;
SELECT age FROM person WHERE id = person_id INTO person_age;

RETURN person_age;

END$$
----------------------
test the result:

select getage(1)$$ --&gt result = 12
select getage(2)$$ --&gt result = 34

運行正常

------------------------------------------------

 

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

(2)FUNCTION 中的分支

[1] IF - THEN - ELSE 分支
 語法 :
 IF comdition THEN
  commands;
 END IF;
 -------------------------
 IF comdition THEN
  commands;
 ELSE
  commands
 END IF;
 -------------------------
嵌套 IF comdition THEN
  commands;
 ELSE  IF comdition THEN
   commands;
  [ELSE commands;]
  END IF;
 END IF;
 -------------------------
 
 
[2] CASE 分支
語法:
--------------------------------
CASE expression

WHEN value1 THEN commands;

WHEN value2 THEN commands;

.......

WHEN value_n THEN commands;
 
ELSE commands;

END CASE;
--------------------------------

example-002:

CREATE FUNCTION personstate (age int)
RETURNS varchar(30)
BEGIN
 DECLARE personstate varchar(30) DEFAULT "UNKNOWN";
 IF age < 0 THEN SET personstate = "UNBORN";
 ELSE
  SET personstate = "BORN";
 END IF;  
RETURN personstate;

END$$

-----------------
select personstate(-3)   ----&gt result = UNBORN;
select personstate(3)    ----&gt result =  BORN;



------------------------------------


 example-003:

DROP FUNCTION  personstate$$

CREATE FUNCTION personstate (age int)
RETURNS varchar(30)
BEGIN
 DECLARE personstate varchar(30) DEFAULT "UNKNOWN";
 IF age < 0 THEN SET personstate = "UNBORN";
 ELSE
  IF age >0 && age<=14 THEN SET personstate ="CHILD"; END IF;
  IF age >14 && age <=22 THEN SET personstate ="YANG"; END IF;
  IF age >22 && age<60 THEN SET personstate = "STRONG"; END IF;
IF age >60 THEN SET personstate = "OLD"; END IF;
 END IF;  
RETURN personstate;

END$$

---------

select personstate(-3)$$ result = UNBORN
select personstate(5)$$ result = CHILD
select personstate(16)$$ result = YANG
select personstate(28)$$ result = STRONG
select personstate(66)$$ result = OLD


TEST IS OK.

----------------------------------------
example-004:

DROP FUNCTION showIn$$

CREATE FUNCTION showIn( valueIn int)
RETURNS VARCHAR(50)
BEGIN

DECLARE str varchar(30) DEFAULT "UNKNOWN";

 CASE valueIn
 
 WHEN 1 THEN SET str = "you input is 1";
 WHEN 2 THEN SET str = "you input is 2";
 WHEN 3 THEN SET str = "you input is 3";
 WHEN 4 THEN SET str = "you input is 4";
 WHEN 5 THEN SET str = "you input is 5";
 
 ELSE SET str = "you input is not 1,2,3,4,5";
 
 END CASE;
RETURN str;
 
END$$

-------------------

select showIn(1)$$  result = you input is 1
select showIn(2)$$  result = you input is 2
select showIn(6)$$  result = you input is not 1,2,3,4,5

TEST IS OK


----------------------------------------



&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

(3)FUNCTION 中的循環

[1] REPEAT-UNTIL 循環
[2] WHILE 循環
[3]  LOOP 循環


 * REPEAT-UTIL 循環
  
  語法:
   [loopname:] REPEAT
    commands;
   UNTIL condition
   END REPEAT [loopname];
   
   說明:
   和 do {} while(condition) 語句的功能一樣。先運行,后判斷。
   當condition 為true的時候 放棄循環 
   
   
 * WHILE 循環
 
  語法:
 
   [loopname :] WHILE condition DO
    commands;
   END WHILE [loopname];
 
   說明: 和 while(condition) {commands; } 語句功能一樣。 先判斷,后執行。
   當condition 為 false 的時候 放棄循環
   
 
 * LOOP 循環
 
  語法:
   
   loopname: LOOP
    commands;
    IF condition THEN LEAVE loopname ; END IF;
   END LOOP loopname;
   
   說明 : 這是一個沒有條件判斷的循環。可以認為是一個死循環。
   除非執行LEAVE 命令來跳出循環,否則循環將永遠被執行。
   
 
 * LEAVE
 
   語法:
   LEAVE loopname ;
   
   說明:
   LEAVE loopname 命令見是程序代碼的執行流程跳出并且結束一個循環。
   LEAVE loopname 命令還可以用來提前退出BEGIN - END 語句塊。
   LEAVE loopname 命令相當于 C 或則 JAVA中 跳出循環的 BREAK  命令
   
   
 * ITERATE
 
   語法:
   ITERATE loopname ;
   
   說明:
   TERATE loopname 命令是跳出當次循環,接下來執行下一次循環。
   TERATE loopname 命令只能在循環體內運行。
   TERATE loopname 命令相當于 C 或則 JAVA中 跳出循環的 CONTINUE  命令
   
-------------------------

example-005:

  DROP FUNCTION getString$$

CREATE FUNCTION getString(number int(11))
  RETURNS VARCHAR(50)
  BEGIN
   declare str varchar(50) default '';
   declare i int default 0;
   
   myloop: REPEAT
    SET i = i+1;
    set str = concat(str,"*");
   
   UNTIL i>=number
   END REPEAT myloop;
  RETURN str;
  END $$
 
  -------------
  select getString(3)$$
  select getString(4)$$
  select getString(8)$$
 
  TEST IS OK
 
 

-------------------------

example-006:

  DROP FUNCTION getString$$
 
  CREATE FUNCTION getString(number int(11))
  RETURNS VARCHAR(50)
  BEGIN
 
   declare str varchar(50) default "";
   declare i int default 0;
   myloop: WHILE i<number DO
set i = i+1;
    set str = concat(str,"@");
   END WHILE myloop;
   
   return str;
   
  END$$
 
  --------
  select getString(3)$$
  select getString(4)$$
  select getString(8)$$
 
  TEST IS OK
 
  -------------------------
  example-007:
 
  DROP FUNCTION getString$$
 
  CREATE FUNCTION getString(number int(11))
  RETURNS VARCHAR(50)
  BEGIN
   declare str varchar(50) default "";
   declare i int default 0;
   
   myloop:LOOP
    set i = i+1;
    IF i>number THEN LEAVE myloop; END IF;
   
    set str= concat(str,"# ");
   
   END LOOP myloop;
   
   RETURN str;
 
  END$$
 
  ---------
  select getString(3)$$
  select getString(4)$$
  select getString(8)$$
 
  TEST IS OK
 
  -----------------------------
  -----------------------------
 
  example-iterate :
 
  DROP FUNCTION getString$$
 
  CREATE FUNCTION getString(number int(11))
  RETURNS VARCHAR(50)
  BEGIN
   declare str varchar(50) default "";
   declare i int default 0;
   
   myloop:LOOP
    set i = i+1;
    IF i%2 = 0 THEN ITERATE myloop ; END IF;
    IF i>number THEN LEAVE myloop; END IF;
   
   
    set str= concat(str,"# ");
   
   END LOOP myloop;
   
   RETURN str;
 
  END$$
 
 
     
 
 
   
   &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
               基本語法規則   <摘錄mysql 5.0="" p="" 296-297="">
   &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

通過對FUNCTION的了解,我們已經對SP的語法規則有了大體的了解。
在FUNCTION 中的變量定義規則,變量賦值規則,分支規則 和 循環規則 同樣也適用于 PROCEDURE。

現在我們來對SP的語法規則進行規范的認識:

# 分號 (;) 。 同一個SP可以包含任意多條SQL命令。這些命令必須用分號格開,就連分支和循環的控制結構也必須用分號結束。

# BEGIN - END 。 沒有落在SP關鍵字之間(如 THEN 和 END IF 之間) 的多條SQL命令必須放在關鍵字BEGIN 和 END 之間。
 這就意味著由多條SQL命令構成的SP的代碼都必須以BEGIN開始,以END結束。

# 換行符。 換行符在SP代碼中的語意效果與空格字符相同。這意味著把 IF-THEN-ELSE-END-IF 結構連續寫在同一行或分開寫在多行上都是可以的。

# 變量 。 供SP內部使用的局部變量 和 局部參數不加 "@" 前綴。 在SP內允許使用普通的SQL變量,但是他們必須加上"@"前綴。
  (加"@"前綴的變量是普通全局變量。對變量疑問,可以參考 《MYSQL變量》 這個部分。)
 
# 字母大小寫情況。 SP 在定義 和調用時均不分字母大小寫情況。它寫成(比如說)shorten , SHORTEN , Shorten 的效果都是一樣的。

# 特殊字符。 在SP中避免使用特殊字符。 總之MYSQL對特殊字符的支持還不是很好。

# 注釋。 "--" 開始并且一直到這一行的結尾都是注釋





    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
                                         查看和刪除SP的方法
    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

(1) 查看FUNCTION
 show function status
 
 show CREATE FUNCTION functionname
 
 select routine_name ,routine_type,routine_schema,created from information_schema.routines where routine_schema = '你的數據庫名' and routine_type='FUNCTION'
 
 例如:
 select routine_name ,routine_type,routine_schema,created from information_schema.routines where routine_schema = 'WYD' and routine_type='function'
 
 
 DROP FUNCTION [IF EXISTS] function_name
 
(2) 查看PROCEDURE

 SHOW PROCEDURE STATUS
 
 show CREATE PROCEDURE functionname
 
 select routine_name ,routine_type,routine_schema,created from information_schema.routines where routine_schema = '你的數據庫名' and routine_type='PROCEDURE'
 
 例如:
 select routine_name ,routine_type,routine_schema,created from information_schema.routines where routine_schema = 'WYD' and routine_type='PROCEDURE'
 
 
 DROP PROCEDURE [IF EXISTS] procedure_name

(3) 查看所有SP
 desc information_schema.routines
 
 select routine_name ,routine_type,routine_schema,created from information_schema.routines
 
 



    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
                                                    MYSQL變量
    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
   
    MYSQL允許人們把簡單的值(離散值,不是象SELECT查詢結果那樣的集合或列表)保存在變量里。在日常應用里,需要用到MySQL變量的時候不多;但是對存儲過程來說,變量卻是非常重要的SQL元素。MySQL里的變量可以分為3類:
    $ 普通變量。
     這類變量的標志是以字符@開頭,他們在SQL連接被關閉時將失去內容。
   
    $ 系統變量和服務器變量。
     這類變量的內容是MySQL服務器的工作狀態或屬性,他們的標志是以"@@"字符串開頭。
   
    $ 存儲過程里的局部變量。
     這些變量是在存儲過程內部聲明的,只在存儲過程內有效。他們沒有統一的特殊標志,但是變量名必須與數據表和數據列名區別。
     局部變量在使用前必須要用DECLARE命令對他們做出聲明。局部變量的內容在過程或函數退出的時候丟失。
   
   普通全局變量的聲明和賦值:
   例子: set @varname = 3
   
    select @total :=count(*) from table_a
   
    select money from book where id =3 into @bookmoney
   
   查詢:
   例子: select @varname
   
   
   
   

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
                                                       PROCEDURE
    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
   
    PROCEDURE [databasename.]procedure_name([IN or OUT or INOUT ] parametername datatype )
    BEGIN
   
     commands;
     
    END
   
   
    ----------------
   
    存儲過程的參數:
    關鍵字 IN ,OUT ,INOUT 用來區分有關參數的用途是僅限制于輸入數據、僅限于輸出數據 還是 輸入輸出數據均可的。(默認設置是IN)
   
   
    ----------------
   
    PROCEDURE局部變量的定義和局部變量的賦值
   
     :同FUNCTION的局部變量的定義和局部變量的賦值
     
   
    -----------------
    example-007:
    題目:寫一個加法的PROCEDURE, 輸入兩個數字。PROCEDURE輸出他們的和
   
    delimiter $$
   
    DROP PROCEDURE IF EXISTS p_addition
   
    CREATE PROCEDURE p_addition(IN v1 int, IN v2 int ,OUT sum int)
    BEGIN
     set sum = v1+v2;
    END$$
   
    ---------
    CALL p_addition(12,45,@sum)$$
   
    select @sum $$
   
    TEST IS OK
   
    ----------------------------------
   
    ----------------------------------
    example-008
   
    題目: 有一張student表,有學生名字段和總分字段。
    我們寫一個PROCEDURE,只要調用這個PROCEDURE ,輸入 學生名 和 總分。 它就幫助我們把該學生寫入數據表中。
   
    delimiter $$
   
    CREATE TABLE student(
    id int(11) primary key auto_increment,
    name varchar(50),
    score int(5)
    )$$
   
    -----
   
    DROP PROCEDURE IF EXISTS p_addStudent$$
   
    -----
   
    CREATE PROCEDURE p_addStudent(IN p_name VARCHAR(50) ,IN p_score INT)
    BEGIN
     insert into student(name,score)values(p_name,p_score);
   
    END$$
   
    -----
    CALL p_addStudent('Petter',199)$$
    CALL p_addStudent('Helen',209)$$
    CALL p_addStudent('Jacker',238)$$
   
    select * from student $$
   
    --------TEST IS OK
   
    --------------------------------------
    --------------------------------------
   
    example-009
   
    題目: 有一張person表 表中有多個字段。
    name ,age , state
    我們寫一個PROCEDURE,只要調用這個PROCEDURE ,輸入人名 和 年齡。 它就幫我們判斷state,并寫入數據庫。
    如果年齡<0 ,state = 'UNBORN'
0 <=如果年齡<12,state = 'CHILD'
12<=如果年齡<22,state = 'YANG'
22<=如果年齡<60,state = 'STRONG'
60<=如果年齡,state = 'OLD'
   
   
    delimiter $$
   
    drop table person$$
   
    create table person(
    id int(11) primary key auto_increment,
    name varchar(50),
    age int(3),
    state varchar(50)
    )$$
   
   
    DROP PROCEDURE IF EXISTS p_addPerson $$
   
   
    CREATE PROCEDURE p_addPerson(IN p_name varchar(50),IN p_age INT(3))
    BEGIN
     declare p_state varchar(50) default "UN_KNOW";
     
     IF p_age < 0 THEN SET p_state = "UNBORN";
 ELSE
  IF p_age >0   && p_age<12 THEN SET p_state ="CHILD";   END IF;
IF p_age >=12 && p_age<22 THEN SET p_state ="YANG";    END IF;
IF p_age >=22 && p_age<60 THEN SET p_state = "STRONG"; END IF;
IF p_age >=60              THEN SET p_state = "OLD";    END IF;
 END IF;
 
 INSERT INTO person(name,age,state) values(p_name,p_age,p_state) ;
   
    END$$
   
    ------------------
    CALL p_addPerson('Pet',11) $$
    CALL p_addPerson('Tom',21) $$
    CALL p_addPerson('Joy',74) $$
    CALL p_addPerson('Soy',-4) $$
   
    SELECT * from person $$
   
    ----- TEST IS OK ----
   
   
   
   
   
   
    --------------------------------------------------
    --------------------------------------------------
   
    example-010
   
    題目:有一張表 goods ,3個字段 id ,name,price. 表中有很多記錄。
    現在我們要寫一個PROCEDURE ,把里面的每個商品的價格都修改為原來的80%.
   
   
    delimiter $$
   
    drop table goods$$
   
    create table goods(
     id int(11) primary key auto_increment,
     name varchar(50),
     price float(6,2) default 0000.00
    )$$
   
   
    insert into goods(name,price)values('goods_01',77.56)$$
    insert into goods(name,price)values('goods_02',147.56)$$
    insert into goods(name,price)values('goods_03',156.36)$$
    insert into goods(name,price)values('goods_04',58.36)$$
    insert into goods(name,price)values('goods_05',458.68)$$
    insert into goods(name,price)values('goods_06',485.55)$$
    insert into goods(name,price)values('goods_07',785.22)$$
    insert into goods(name,price)values('goods_08',45.36)$$
    insert into goods(name,price)values('goods_09',47.36)$$
    insert into goods(name,price)values('goods_10',456.36)$$
    insert into goods(name,price)values('goods_11',654.85)$$
    insert into goods(name,price)values('goods_12',785.25)$$
   
   
    ------------
    DROP PROCEDURE IF EXISTS p_goods $$
   
    CREATE PROCEDURE p_goods()
    BEGIN
     
     DECLARE p_id INT DEFAULT 0;
     DECLARE p_id_min INT DEFAULT 0;
     DECLARE p_id_max INT DEFAULT 0;
     DECLARE p_id_current INT DEFAULT 0;
     DECLARE p_name_current VARCHAR(50) DEFAULT "UNKNOW";
     DECLARE p_price FLOAT(6,2) DEFAULT 0;
     
     select min(id),max(id) from goods into p_id_min ,p_id_max;
     
     SET p_id = p_id_min;
     
     goods_loop : LOOP
     
      select id,name,price from goods where id = p_id into p_id_current,p_name_current,p_price;
     
      IF p_id_current!=0 THEN
     
       set p_price = p_price * 0.8;
       
       update goods set price = p_price where id = p_id;
       
       set p_id_current=0;
       
      END IF;
     
      set p_id = p_id + 1;
     
      IF p_id > p_id_max THEN LEAVE goods_loop; END IF;
     END LOOP goods_loop;
   
   
    END $$
   
------------------------------------  
   
mysql> select * from goods;
   -> $$
+----+----------+--------+
| id | name     | price  |
+----+----------+--------+
|  1 | goods_01 |  77.56 |
|  2 | goods_02 | 147.56 |
|  3 | goods_03 | 156.36 |
|  4 | goods_04 |  58.36 |
|  5 | goods_05 | 458.68 |
|  6 | goods_06 | 485.55 |
|  7 | goods_07 | 785.22 |
|  8 | goods_08 |  45.36 |
|  9 | goods_09 |  47.36 |
| 10 | goods_10 | 456.36 |
| 11 | goods_11 | 654.85 |
| 12 | goods_12 | 785.25 |
+----+----------+--------+

----------------------------------------
CALL  p_goods() $$

----------------------------------------
mysql> CALL p_goods() $$
Query OK, 1 row affected (0.13 sec)

mysql>  select *from goods$$
+----+----------+--------+
| id | name     | price  |
+----+----------+--------+
|  1 | goods_01 |  62.05 |
|  2 | goods_02 | 118.05 |
|  3 | goods_03 | 125.09 |
|  4 | goods_04 |  46.69 |
|  5 | goods_05 | 366.94 |
|  6 | goods_06 | 388.44 |
|  7 | goods_07 | 628.18 |
|  8 | goods_08 |  36.29 |
|  9 | goods_09 |  37.89 |
| 10 | goods_10 | 365.09 |
| 11 | goods_11 | 523.88 |
| 12 | goods_12 | 628.20 |
+----+----------+--------+
12 rows in set (0.00 sec)

---------------------------------------
example-010 TEST IS OK  ,Finished


---------------------------------------
---------------------------------------


$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
                                異常捕獲
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$


SP里面的SQL命令在執行的過程中可能會出錯,所以MYSQL也像其他一些程序語言一樣向程序員提供一種利用 ‘異常處理器’來響應和處理這類錯誤的機制。

在一個BEGIN - END 語句塊里,對‘異常處理器’的定義必須出現在變量,光標,出錯條件的聲明之后。在其他SQL命令之前。

語法:

DECLARE type HANDLER FOR condition1[,condition2,condition3,.......] handler_action

下面對語法中的type , condition , handler_action 來進行解釋:

<1>type(異常捕獲處理類型) 。可以選擇的類型目前只有 CONTINUE 和 EXIT 兩種。(未來的MySQL版本可能會增加第3種選擇:UNDO)
CONTINUE : 如果當前命令在執行時發生錯誤,繼續執行下一條命令。
EXIT     : 如果當前命令在執行時發生錯誤,跳出當前的BEGIN - END 語句塊。

<2>condition (捕獲異常條件)。這里可以列出一個到多個捕獲異常條件。它們是異常處理器要捕捉的目標。捕獲異常條件可以用以下幾種方式給出:

SQLSTATE 'errorcode'  單個SQL異常代碼,編號是errorcode
SQLWARNING   含蓋了SQLSTATE編號為01nnn的所有異常
NOT FOUND   含蓋了所有其他的(即SQLSTATE編號不是01 和 02開頭的)的異常
mysqlerrorcode   這個數字是MySQL異常的代碼而不是一個SQLSTATE異常的代碼
conditionname   用一個DECLARE CONDITION 命令定義的異常,conditionname是異常的名字

<3>handler_action 異常被拋出時要執行的命令。它將在異常拋出后, CONTINUE or EXIT 執行前運行。
  因為這里只能放上一條命令,所以通常它是一個變量賦值命令。
 
 
-------------------------------------------------------------------
聲明異常捕獲條件(自定義異常)
所謂的"聲明異常捕獲" 就是給異常編碼定義一個簡明易記的名字。
定義一定要在異常出現以前定義。定義出來的異常捕獲名可以用在出錯的異常捕獲器定義中。

語法:
DECLARE condition_name CONDITION FOR {SQLSTATE sqlstate_code | MySQL_error_code};

例:
DECLARE foreign_key_error CONDITION FOR 1216;
DECLARE CONTINUE HANDLER FOR foreign_key_error MySQL_statements;

優先級:

當同時使用MySQl錯誤碼,標準SQLSTATE錯誤碼,命名條件(SQLEXCEPTION)來定義錯誤處理時,其捕獲順序是(只可捕獲一條錯誤):

MySQl錯誤碼---&gtSQLSTATE錯誤碼---&gt命名條件(SQLEXCEPTION)

具體的SQL_STATE 請參考


--------------------------------------------------------------------
異常的觸發

MYSQL中異常的出發只能靠執行非法代碼來實現。 而不能如同Oracle,直接有"RAISE Exception"來實現的。

--------------------------------------------------------------------

SP中的打印語句。
我們在Oracle中寫存儲過程,會很常用到一個打印函數“DBMS_OUTPUT.PUT_LINE('要打印的內容');”
很可惜,在MySQL中沒有類似的函數。
但是我們可以通過變通來實現該功能。
利用 SELECT '我們想要讓計算機打印出來的內容'  來實現。
語法:

SELECT "Content" as result;
SELECT CONCAT(A1,A2[,A3,A4,.....]) as result ;

寫一個例子:
example-011

delimiter $$


--------
DROP PROCEDURE IF EXISTS p_print $$


--------
CREATE PROCEDURE p_print()
BEGIN

DECLARE i int default 1;

myloop : LOOP

select concat("這是第",i,"次顯示數據") as printResult;

set i=i+1;
IF i>10 THEN   LEAVE myloop; END IF;

END LOOP myloop;

END$$

---------
call p_print()$$

----------------------------------------
example-012

寫一個循環 ,我們來循環捕捉錯誤。

delimiter $$
--------------
DROP PROCEDURE IF EXISTS p_exception $$
--------------
CREATE PROCEDURE p_exception()
BEGIN

DECLARE num int default 0;

DECLARE table_notfound_error CONDITION FOR 1146 ;


DECLARE CONTINUE HANDLER FOR table_notfound_error SELECT CONCAT("TABLE is not exit FOR ---",num) as message;


myloop:LOOP
set num = num + 1;
select * from exception; -- 1146 errorcode

IF num >= 10 THEN

LEAVE myloop;

END IF;

END LOOP myloop;

END$$

-----------------
TEST IS OK

-----------------------------------------------------
-----------------------------------------------------


$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
                             游標
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

說起游標,我就想起了Oracle中的游標。 如果你沒有學習過Oracle中的游標,沒有關系。因為MYSQL的游標更簡單。

游標(CURSOR):是構建在MYSQL中,用來查詢數據,獲得記錄集合的指針。他可以讓開發者一次訪問結果集中一行。

MYSQL 中只有顯式游標 這 一種游標。

--------------------------------
游標的使用方法(使用過程)。

(1)聲明游標。
(2)打開游標。
(3)從游標中獲取記錄。
(4)關閉游標。

---------------------------------

(1)聲明游標。
語法 :

DECLARE cursorname CURSOR FOR "YOUR SQL";

--------

(2)打開游標。

OPEN cursorname;

--------

(3)從游標中獲取記錄。

FETCH cursorname INTO v1,v2,....;

在ORACEL 中,游標中沒有數值的時候 %FOUND 就會 返回一個 FALSE。
但是在MYSQL 中FETCH 到最后就會觸發一個1329號錯誤 "No data to fetch".相應的SQLSTATE 為 02000。
這個異常是無法避免的,所以我們都會用異常捕捉器來捕捉它。(可以直接聲明一個對應的異常捕捉器,也可以聲明一個 NOT FOUND 的異常捕捉器)

---------

(4)關閉游標。

CLOSE cursorname 。

注釋: 其實這樣做 也就增加邏輯性。其實光標會在BEGIN - END 塊結束的時候自動關閉。所以很多程序員都不會手動關閉游標。

-----------------------

實例練習:
example-013

題目,創建一個多字段的表 student ,有 id, name ,intime 三個字段。里面寫入有多行記錄。
用游標來獲得里面的所有 記錄,并且 一行一行的輸出。

--------------
delimiter $$

--------------
DROP TABLE IF EXISTS student $$

--------------
CREATE TABLE student(
id int primary key auto_increment,
name varchar(50),
intime timestamp(14)
)$$

--------------

insert into student(name,intime) values('s-1','1999-08-25 12:30:30')$$
insert into student(name,intime) values('s-2','1999-08-25 12:30:30')$$
insert into student(name,intime) values('s-3','1999-08-25 12:30:30')$$
insert into student(name,intime) values('s-4','1999-08-25 12:30:30')$$
insert into student(name,intime) values('s-5','1999-08-25 12:30:30')$$
insert into student(name,intime) values('s-6','1999-08-25 12:30:30')$$
insert into student(name,intime) values('s-7','1999-08-25 12:30:30')$$
insert into student(name,intime) values('s-8','1999-08-25 12:30:30')$$
insert into student(name,intime) values('s-9','1999-08-25 12:30:30')$$

commit $$
---------------

DROP PROCEDURE IF EXISTS p_readcursor $$

---------------

CREATE PROCEDURE p_readcursor()
BEGIN


DECLARE p_id int default 0;
DECLARE p_name varchar(50) default "unknow";
DECLARE p_intime timestamp(14) default '0000-00-00 00:00:00';

DECLARE student_cursor CURSOR FOR select id,name,intime from student;

DECLARE EXIT HANDLER FOR 1329 SELECT "CURSOR IS END --&gt OK" as message;

OPEN student_cursor;

myloop: LOOP

FETCH student_cursor into p_id,p_name,p_intime;

IF p_id=100 THEN LEAVE myloop; END IF;

select p_id,p_name,p_intime ;

END LOOP myloop;

CLOSE student_cursor;


END $$

----------------
call p_readcursor()$$


-------TEST IS OK----------
---------------------------


$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  觸發器
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$


觸發器的用途是 在INSERT 、UPDATE 、DELETE命令之前 或則 之后自動調動SQL命令或SP。比如說,可以為每一個UPDATE操作測試被修改的數據是否滿足特定條件。
在MYSQL5.0里邊觸發器還很不完善。與SP相比,觸發器還遠沒有成熟到可以用于實際應用程序中的地步。根據MySQL在線文檔里的說法,MYSQL5.1版本中將提供更多觸發器的功能。
在5.1版本出來以前,觸發器只能完成一些很初級的任務。

(1)創建觸發器
(2)查詢數據庫中的觸發器
(3)刪除觸發器

------------------------------
(1) 創建觸發器

語法:

CREATE TRIGGER trigger_name BEFORE|AFTER INSERT|UPDATE|DELETE
ON tablename [FOR EACH ROW]
BEGIN
commands;
END


注釋: * 最多可以為同一個數據表定義6個觸發器,分別為 INSERT , UPDATE 或 DELETE 命令的前 , 后各定義一個。
* 觸發器的名字在同一個數據庫中必須唯一。
* 觸發器代碼體要 以 BEGIN 開始, END 結束。

功能局限:
* 觸發器代碼里無法訪問任何數據表,就連觸發器為之定義的那個數據表也不能訪問。自然就不能使用 DELETE,UPDATE,INSERT 來修改數據庫表。
* MySQL沒有提供可以用來取消DELETE,UPDATE,INSERT命令的命令或語法元素。
* 在觸發器代碼里不能調用事務命令。

OLD and NEW

在觸發器代碼里,可以通過以下方式去訪問當前記錄的各個字段。
OLD.columname 返回一條現有記錄在被刪除或修改之前的內容(UPDATE,DELETE).
NEW.columname 返回一條新記錄或被修改記錄的新內容(INSERT ,UPDATE).

---------------------------------
(2)查詢數據庫中的觸發器

暫時還沒相關命令來查看自定義的觸發器。(他們做地太差了,HOHO)

---------------------------------
(3)刪除觸發器

語法:
DROP TRIGGER [databasename.]triggername

注釋: 刪除trigger不支持 IF EXISTS 變體。


---------------------------------
做一個例子:

example-014

delimiter $$

--------------
DROP TABLE IF EXISTS student_score$$

--------------
CREATE TABLE student_score (
id int primary key auto_increment,
name varchar(50),
score int
)$$

--------------

DROP TRIGGER student_score_insert_before$$

--------------

CREATE TRIGGER student_score_insert_before
BEFORE INSERT ON student_score FOR EACH ROW
BEGIN

IF NEW.score<0 or="" new.score="">100 THEN
SET NEW.score = 0;
END IF;

END$$

--------------

Insert into student_score(name,score)values('ZhangSan',12)$$
Insert into student_score(name,score)values('LiSi',-12)$$
Insert into student_score(name,score)values('WangWu',112)$$

mysql> select * from student_score$$
+----+----------+-------+
| id | name     | score |
+----+----------+-------+
|  1 | ZhangSan |    12 |
|  2 | LiSi     |     0 |
|  3 | WangWu   |     0 |
+----+----------+-------+

筆記結束,祝賀大家學習愉快.

上述就是小編為大家分享的怎么理解MySQL存儲過程和觸發器了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

双柏县| 嘉峪关市| 黄陵县| 文化| 镶黄旗| 丰台区| 洛阳市| 尚志市| 屯留县| 巫山县| 辽阳县| 眉山市| 仪陇县| 深州市| 呼玛县| 五指山市| 综艺| 弋阳县| 桂平市| 襄城县| 长葛市| 聂荣县| 江永县| 当雄县| 湖南省| 北安市| 克什克腾旗| 岱山县| 黄平县| 高唐县| 神池县| 惠安县| 昌吉市| 盱眙县| 娄烦县| 鹤山市| 花垣县| 黔南| 荆门市| 衡阳市| 隆子县|