在MySQL遊標中,能夠聲明DECLARE CONTINUE HANDLER來操做1個越界標誌。sql
語法:DECLARE CONTINUE HANDLER FOR NOT FOUND STATEMENT;數據庫
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的方式釋放遊標資源。緩存
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 ;
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;
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支持""。服務器
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 (?,?,?)";函數
方法一:測試
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
DROP TABLE EMP_T1,EMP_T2;
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)結果:
不能夠!自定義函數不支持建立表,無論是正常表仍是臨時表。(SQL Server自定義函數,也不支持臨時表,可是支持表變量。)
事務(Transaction)是訪問和更新數據庫的程序執行單元;事務中可能包含一個或多個sql語句,這些語句要麼都執行,要麼都不執行。
如上圖所示,MySQL邏輯架構從上往下能夠分爲三層:
1)第一層:處理客戶端鏈接、受權認證等。
2)第二層:服務器層,負責查詢語句的解析、優化、緩存以及內置函數的實現、存儲過程等。
3)第三層:存儲引擎,負責MySQL中數據的存儲和提取。
說明1:MySQL中服務器層無論理事務,事務是由存儲引擎實現的。
說明2:MySQL支持事務的存儲引擎有InnoDB、NDB Cluster等,其中InnoDB的使用最爲普遍;其餘存儲引擎不支持事務,如MyIsam、Memory等。
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。
SET AUTOCOMMIT=1 開啓自動提交
SET AUTOCOMMIT=0 禁止自動提交
默認是開啓自動提交,能夠使用如下命令查詢:
SHOW VARIABLES LIKE 'AUTOCOMMIT';
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表明無報錯。