MySQL學習筆記十:遊標/動態SQL/臨時表/事務

1、遊標

1.一、越界標誌

在MySQL遊標中,能夠聲明DECLARE CONTINUE HANDLER來操做1個越界標誌。sql

語法:DECLARE CONTINUE HANDLER FOR NOT FOUND STATEMENT;數據庫

1.二、REPEAT方式

DELIMITER $$
CREATE PROCEDURE CHANGESEX ()
BEGIN
    DECLARE HAVE INT DEFAULT 1;
    DECLARE PID INT;
    
    DECLARE CURT CURSOR FOR SELECT ID FROM STUDY11;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET HAVE=0;
    OPEN CURT;
    FETCH CURT INTO PID;
    REPEAT
        UPDATE STUDY11 SET SEX=CASE SEX WHEN '' THEN 'MALE' ELSE 'FEMALE' END WHERE ID=PID;
        FETCH CURT INTO PID;
    UNTIL HAVE=0 END REPEAT;
    CLOSE CURT;
END$$
DELIMITER ;

須要注意的是:MySQL不能像SQL Server那樣,使用DEALLOCATE的方式釋放遊標資源。緩存

1.三、WHILE方式

DELIMITER $$
CREATE PROCEDURE CHANGESEX1 ()
BEGIN
    DECLARE HAVE INT DEFAULT 1;
    DECLARE PID INT;
    
    DECLARE CURT CURSOR FOR SELECT ID FROM STUDY11;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET HAVE=0;
    OPEN CURT;
    FETCH CURT INTO PID;
    WHILE HAVE=1 DO
        UPDATE STUDY11 SET SEX=CASE SEX WHEN 'MALE' THEN '' ELSE '' END WHERE ID=PID;
        FETCH CURT INTO PID;
    END WHILE;
    CLOSE CURT;
END$$
DELIMITER ;

2、動態SQL

2.一、動態SQL格式

SET SQL= (預處理的SQL語句,能夠使用CONCAT拼接的語句,參數用 ?代替 。);

SET @SQL=SQL;

PREPARE STMT_NAME FROM @SQL;

SET @VAR_NAME=XXX;

EXECUTE STMT_NAME [USING @VAR_NAME[,@VAR_NAME]...];

{DEALLOCATE | DROP} PREPARE STMT_NAME;

2.二、動態SQL示例

DELIMITER $$
CREATE PROCEDURE GETNAME (IN PID INT)
BEGIN
    #定義預處理SQL語句
    DECLARE STRSQL VARCHAR(1000);
    
    #拼接SQL語句
    SET STRSQL="SELECT NAME FROM EMP WHERE ID=?";
    
    #將自定義變量賦值給用戶變量
    SET @SQL=STRSQL;
    
    #預處理動態SQL語句
    PREPARE STMT FROM @SQL;
    
    #傳遞動態SQL參數
    SET @PARAM1=PID;
    
    #執行動態SQL語句
    EXECUTE STMT USING @PARAM1;
    
    #釋放PREPARE
    DEALLOCATE PREPARE STMT;
END$$
DELIMITER ;

能夠看出,MySQL動態SQL支持""。服務器

2.三、動態SQL注意事項

1)存儲動態SQL的值的變量不能是自定義變量,必須是用戶變量或者全局變量 。如:SET SQL='XXX';PREPARE STMT FROM SQL;都是錯誤的寫法,正確的寫法爲:SET @SQL='XXX';PREPARE STMT FROM @SQL; 架構

2)即便PREPARABLE_STMT語句中的 ? 所表明的是一個字符串,也不須要用引號將 ? 兩邊包起來。ide

3)若是動態語句中用到了 IN ,則SQL語句能夠寫成:SET STRSQL="SELECT NAME FROM EMP WHERE ID IN (?,?,?)";函數

3、臨時表

3.一、臨時表建立

方法一:測試

CREATE TEMPORARY TABLE `emp_t1` (
  `ID` int(11) DEFAULT NULL,
  `NAME` varchar(50) DEFAULT NULL,
  `AGE` int(11) DEFAULT NULL,
  KEY `ID_INDEX` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

方法二:優化

CREATE TEMPORARY TABLE emp_t2 SELECT * FROM EMP WHERE ID<=10;

能夠看出,MySQL並不支持像SQL Server那樣使用SELECT * INTO #EMP FROM EMP的方式來建立臨時表。spa

3.二、臨時表刪除

DROP TABLE EMP_T1,EMP_T2;

3.三、臨時表測試(存儲過程)

1)建立:

DELIMITER $$
CREATE PROCEDURE TempTest1 ()
BEGIN
    #臨時表建立方式一測試
    CREATE TEMPORARY TABLE `emp_t1` (
        `ID` int(11) DEFAULT NULL,
        `NAME` varchar(50) DEFAULT NULL,
        `AGE` int(11) DEFAULT NULL,
        KEY `ID_INDEX` (`ID`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    INSERT INTO EMP_T1 SELECT * FROM EMP LIMIT 10;
    
    #臨時表建立方式二測試
    CREATE TEMPORARY TABLE emp_t2 SELECT * FROM EMP WHERE ID<=10;
    
    #結果返回
    SELECT * FROM EMP_T1 UNION SELECT * FROM EMP_T2;
    
    #臨時表刪除
    DROP TABLE EMP_T1,EMP_T2;
END$$
DELIMITER ;

2)調用:

CALL TempTest1();

3)結果:

3.四、自定義函數能使用臨時表嗎?

不能夠!自定義函數不支持建立表,無論是正常表仍是臨時表。(SQL Server自定義函數,也不支持臨時表,可是支持表變量。)

4、事務

4.一、基礎概念

事務(Transaction)是訪問和更新數據庫的程序執行單元;事務中可能包含一個或多個sql語句,這些語句要麼都執行,要麼都不執行。

4.二、MySQL邏輯架構與存儲引擎

如上圖所示,MySQL邏輯架構從上往下能夠分爲三層:

1)第一層:處理客戶端鏈接、受權認證等。

2)第二層:服務器層,負責查詢語句的解析、優化、緩存以及內置函數的實現、存儲過程等。

3)第三層:存儲引擎,負責MySQL中數據的存儲和提取。

說明1:MySQL中服務器層無論理事務,事務是由存儲引擎實現的。

說明2:MySQL支持事務的存儲引擎有InnoDB、NDB Cluster等,其中InnoDB的使用最爲普遍;其餘存儲引擎不支持事務,如MyIsam、Memory等。

4.三、事務控制語句

1)BEGIN 或 START TRANSACTION 顯式地開啓一個事務;

2)COMMIT 也能夠使用 COMMIT WORK,不過兩者是等價的。COMMIT 會提交事務,並使已對數據庫進行的全部修改爲爲永久性的;

3)ROLLBACK 也能夠使用 ROLLBACK WORK,不過兩者是等價的。回滾會結束用戶的事務,並撤銷正在進行的全部未提交的修改;

4)SAVEPOINT identifier,SAVEPOINT 容許在事務中建立一個保存點,一個事務中能夠有多個 SAVEPOINT;

5)RELEASE SAVEPOINT identifier 刪除一個事務的保存點,當沒有指定的保存點時,執行該語句會拋出一個異常;

6)ROLLBACK TO identifier 把事務回滾到標記點;

7)SET TRANSACTION 用來設置事務的隔離級別。InnoDB 存儲引擎提供事務的隔離級別有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 和 SERIALIZABLE。

4.四、事務提交模式

SET AUTOCOMMIT=1 開啓自動提交

SET AUTOCOMMIT=0 禁止自動提交

默認是開啓自動提交,能夠使用如下命令查詢:

SHOW VARIABLES LIKE 'AUTOCOMMIT';

4.五、事務示例

4.5.一、無判斷語句事務

DELIMITER $$
CREATE PROCEDURE TranTest1 ()
BEGIN
    #臨時表建立
    CREATE TEMPORARY TABLE EMP_T1 SELECT * FROM EMP WHERE 1=2;
    
    #開啓事務
    START TRANSACTION;
    
    #數據插入
    INSERT INTO EMP_T1 VALUES (1,'HELLO',18);
    INSERT INTO EMP_T1 VALUES (2,'WORLD',19);
    
    #提交事務
    COMMIT;
    
    #結果返回
    SELECT * FROM EMP_T1;
    
    #臨時表刪除
    DROP TABLE EMP_T1;
END$$
DELIMITER ;

4.5.二、有判斷語句事務(推薦)

DELIMITER $$
CREATE PROCEDURE TranTest2 ()
BEGIN
    #判斷事務是否異常的錯誤變量
    DECLARE PERROR INT DEFAULT 0;
    DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET PERROR=1;

    #臨時表建立
    CREATE TEMPORARY TABLE EMP_T1 SELECT * FROM EMP WHERE 1=2;
    
    #開啓事務
    START TRANSACTION;

    #數據插入
    INSERT INTO EMP_T1 VALUES (1,'HELLO',18);
    INSERT INTO EMP_T1 VALUES (2,'WORLD',19);
    
    #提交事務
    IF (PERROR=0) THEN
        COMMIT;
    ELSE
        ROLLBACK;
    END IF;
    
    #結果返回
    SELECT * FROM EMP_T1;
    
    #臨時表刪除
    DROP TABLE EMP_T1;
END$$
DELIMITER ;

說明:SQL Server中事務執行是否有報錯,能夠使用@@ERROR來判斷,@@ERROR=0表明無報錯。

相關文章
相關標籤/搜索