1. 程式人生 > >MySQL-5.7 遊標及DECLARE

MySQL-5.7 遊標及DECLARE

簡單的 creat lstat 表達 false lose 特定 key 需要

1.cursor遊標

用來聲明一個數據集
遊標的聲明必須在變量和條件聲明之後,在handler聲明之前

遊標特性:

  • 不靈敏:服務器可以或不復制其結果
  • 只讀:不可更新
  • 不可滾動的:只能在一個方向上遍歷,不能跳過行

實例:

CREATE PROCEDURE curdemo()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  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 NOT FOUND SET done= TRUE;

  OPEN cur1;
  OPEN cur2;read_loop:LOOP
    FETCH cur1 INTO a,b;
    FETCH cur2 INTO c;
    IF done THEN
      LEAVE read_loop;
    END IF;
    IF b<c THEN
      INSERT INTO test.t3 VALUES (a,b);
    ELSE
      INSERT INTO test.t3 VALUES (a,c);
    END IF;
  END LOOP;

  CLOSE cur1;
  CLOSE cur2;
END;

說明:

  • cursor close用來關閉之前打開的遊標;
  • 如果關閉一個未打開的遊標,則MySQL會報錯;
  • 如果在存儲過程和函數中未使用此語句關閉打開的遊標,則遊標會在聲明的begin...end語句塊執行之後自動關閉;

cursor declare用來聲明一個遊標和指定遊標對應的數據集合,通常數據集合是一個select語句。

DECLARE cursor_name CURSOR FOR select_statement

cursor fetch用來獲取遊標指定數據集的下一行數據並將各個字段值賦予後面的變量

FETCH [[NEXT] FROM] cursor_name INTO var_name [, var_name] ...
  • 數據集中的字段需要和INTO語句中定義的變量一一對應
  • 數據集中的數據都fetch完之後,則返回NOT FOUND

2.Declare condition語句

命名特定的錯誤條件,而該特定錯誤可以在declare...handler中指定處理方法
語法:

DECLARE condition_name CONDITION FOR condition_value

condition_value:mysql_error_code
  | SQLSTATE [VALUE] sqlstate_value

說明:
condition_value指定特定的錯誤條件,有以下兩種形式:

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘v1 int default 5;
  • mysql_err_code表示MySQL error code的整數
  • sqlstate_value表示MySQL中用5位字符串表達的語句狀態
DECLARE CONTINUE HANDLER FOR 1051
BEGIN
-- body of handler
END;

declare no_such_table condition for 1051;
declare continue handler for no_such_table
begin
--body of handler
end;

declare no_such_table condition for sqlstate ‘42S02‘
declare continue handler for no_such_table
begin
--body of handler
end;

3.Declare handler語句

語法:

DECLARE handler_action HANDLER
    FOR condition_value [, condition_value] ...
    statement

handler_action:CONTINUE
  | EXIT
  | UNDO

condition_value:mysql_error_code
  | SQLSTATE [VALUE] sqlstate_value
  | condition_name
  | SQLWARNING
  | NOT FOUND
  | SQLEXCEPTION
  • 用來聲明一個handler來處理一個或多個特殊條件,當其中的某個條件滿足時觸發其中的SQL語句執行;
  • SQL可以使一個簡單的語句,也可以是begin...end組成的多個語句;

handler_action聲明當執行完SQL語句之後應該做什麽:

  • CONTINUE表示繼續執行該存儲過程或函數
  • EXIT表示退出聲明此handler的begin...end語句塊
  • UNDO參數已不支持

condition_value的值有以下幾種:

  • mysql_err_code表示MySQL error code的整數;
  • sqlstate_value表示MySQL中用5位字符串表達的語句狀態;
  • condition_name表示之前在declare...condition語句中聲明的名字;
  • SQLWARNING表示所有的警告信息,即sqlstate中01打頭的所有錯誤;
  • NOT FOUND表示查完或查不到數據,即sqlstate中02打頭的所有錯誤;
  • SQLEXCEPTION表示所有的錯誤信息

實例:

DECLARE CONTINUE HANDLER FOR 1051
  BEGIN
    -- body of handler
  END;

DECLARE CONTINUE HANDLER FOR SQLSTATE ‘42S02‘
  BEGIN
    -- body of handler
  END;

DECLARE CONTINUE HANDLER FOR SQLWARNING
  BEGIN
    -- body of handler
  END;

DECLARE CONTINUE HANDLER FOR NOT FOUND
  BEGIN
    -- body of handler
  END;

DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
  BEGIN
    -- body of handler
  END;

當conditon發生但沒有聲明handler時,則存儲過程和函數依照如下規則處理:

  • 發生SQLEXCEPTION錯誤,則執行exit退出;
  • 發生SQLWARNING警告,則執行continue繼續執行;
  • 發生NOT FOUND情況,則執行continue繼續執行;

實例:

mysql> CREATE TABLE test.t(s1 INT, PRIMARY KEY (s1));
Query OK, 0 rows affected (0.35 sec)

SQLSTATE ‘23000‘表示主鍵沖突

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.03 sec)

mysql> delimiter ;
mysql> select @x;
+------+
| @x   |
+------+
|    3 |
+------+
1 row in set (0.00 sec)

實例:

mysql> delimiter //
mysql> create procedure curdemo()
    -> begin
    -> declare done int default false;
    -> declare a char(16);
    -> declare b,c int;
    -> declare cur1 cursor for select id,data from t1;
    -> declare cur2 cursor for select i from test.t2;
    -> declare continue handler for not found set done = true;
    -> open cur1;
    -> open cur2;
    -> read_loop:loop
    -> fetch cur1 into a,b;
    -> fetch cur2 into c;
    -> if done then
    -> leave read_loop;
    -> end if;
    -> if b<c then
    -> insert into test.t3 values(a,b);
    -> else
    -> insert into test.t3 values(a,c);
    -> end if;
    -> end loop;
    -> close cur1;
    -> close cur2;
    -> end//
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;

MySQL-5.7 遊標及DECLARE