国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數據庫 > MySQL > 正文

MySQL 5.0 新特性教程 存儲過程:第二講

2024-07-24 12:57:33
字體:
來源:轉載
供稿:網友

作者:MySQL AB;翻譯:陳朋奕

  Why MySQL Statements are Legal in a PRocedure Body
  什么MySQL語句在存儲過程體中是合法的?

  什么樣的SQL語句在Mysql存儲過程中才是合法的呢?你可以創建一個包含INSERT, UPDATE,DELETE, SELECT, DROP, CREATE, REPLACE等的語句。你唯一需要記住的是如果代碼中包含MySQL擴充功能,那么代碼將不能移植。在標準SQL語句中:任何數據庫定義語言都是合法的,如:

 

CREATE PROCEDURE p () DELETE FROM t; //
  SET、COMMIT以及ROLLBACK也是合法的,如:
CREATE PROCEDURE p () SET @x = 5; //

  MySQL的附加功能:任何數據操作語言的語句都將合法。
CREATE PROCEDURE p () DROP TABLE t; //

  MySQL擴充功能:直接的SELECT也是合法的:
CREATE PROCEDURE p () SELECT 'a'; //

  順便提一下,我將存儲過程中包括DDL語句的功能稱為MySQL附加功能的原因是在SQL標準中把這個定義為非核心的,即可選組件。

  在過程體中有一個約束,就是不能有對例程或表操作的數據庫操作語句。例如下面的例子就是非法的:
CREATE PROCEDURE p1 ()
CREATE PROCEDURE p2 () DELETE FROM t; //

  下面這些對MySQL 5.0來說全新的語句,過程體中是非法的:
CREATE PROCEDURE, ALTER PROCEDURE, DROP PROCEDURE, CREATE FUNCTION,
DROP FUNCTION, CREATE TRIGGER, DROP TRIGGER.

  不過你可以使用
CREATE PROCEDURE db5.p1 () DROP DATABASE db5//

  但是類似
"USE database"

  語句也是非法的,因為MySQL假定默認數據庫就是過程的工作場所。

  Call the Procedure 調用存儲過程
  1.
  現在我們就可以調用一個存儲過程了,你所需要輸入的全部就是CALL和你過程名以及一個括號再一次強調,括號是必須的當你調用例子里面的p1過程時,結果是屏幕返回了t表的內容
mysql> CALL p1() //
+------+
| s1 |
+------+
| 5 |
+------+
1 row in set (0.03 sec)
Query OK, 0 rows affected (0.03 sec)

  因為過程中的語句是
"SELECT * FROM t;"

  2. Let me say that again, another way.
  其他實現方式
mysql> CALL p1() //

  和下面語句的執行效果一樣:
mysql> SELECT * FROM t; //

  所以,你調用p1過程就相當于你執行了下面語句:
"SELECT * FROM t;"

  好了,主要的知識點"創建和調用過程方法"已經清楚了。我希望你能對自己說這相當簡單。但是很快我們就有一系列的練習,每次都加一條子句,或者改變已經存在的子句。那樣在寫復雜部件前我們將會有很多可用的子句。

Characteristics Clauses 特征子句
  1.
CREATE PROCEDURE p2 ()
LANGUAGE SQL <--
NOT DETERMINISTIC <--
SQL SECURITY DEFINER <--
COMMENT 'A Procedure' <--
SELECT CURRENT_DATE, RAND() FROM t //

  這里我給出的是一些能反映存儲過程特性的子句。子句內容在括號之后,主體之前。這些子句都是可選的,他們有什么作用呢?

  2.
CREATE PROCEDURE p2 ()
LANGUAGE SQL <--
NOT DETERMINISTIC
SQL SECURITY DEFINER
COMMENT 'A Procedure'
SELECT CURRENT_DATE, RAND() FROM t //

  很好,這個LANGUAGE SQL子句是沒有作用的。僅是為了說明下面過程的主體使用SQL語言編寫。這條是系統默認的,但你在這里聲明是有用的,因為某些DBMS(IBM的DB2)需要它,如果你關注DB2的兼容問題最好還是用上。此外,今后可能會出現除SQL外的其他語言支持的存儲過程。

  3.
CREATE PROCEDURE p2 ()
LANGUAGE SQL
NOT DETERMINISTIC <--
SQL SECURITY DEFINER
COMMENT 'A Procedure'
SELECT CURRENT_DATE, RAND() FROM t //

  下一個子句,NOT DETERMINISTIC,是傳遞給系統的信息。這里一個確定過程的定義就是那些每次輸入一樣輸出也一樣的程序。在這個案例中,既然主體中含有SELECT語句,那返回肯定是未知的因此我們稱其NOT DETERMINISTIC。但是MySQL內置的優化程序不會注意這個,至少在現在不注意。

  4.
CREATE PROCEDURE p2 ()
LANGUAGE SQL
NOT DETERMINISTIC
SQL SECURITY DEFINER <--
COMMENT 'A Procedure'
SELECT CURRENT_DATE, RAND() FROM t //
  下一個子句是SQL SECURITY,可以定義為SQL SECURITY DEFINER或SQL SECURITY INVOKER。
  這就進入了權限控制的領域了,當然我們在后面將會有測試權限的例子。
SQL SECURITY DEFINER

  意味著在調用時檢查創建過程用戶的權限(另一個選項是SQLSECURITY INVOKER)。
  現在而言,使用
SQL SECURITY DEFINER

  指令告訴MySQL服務器檢查創建過程的用戶就可以了,當過程已經被調用,就不檢查執行調用過程的用戶了。而另一個選項(INVOKER)則是告訴服務器在這一步仍然要檢查調用者的權限。

  5.
CREATE PROCEDURE p2 ()
LANGUAGE SQL
NOT DETERMINISTIC
SQL SECURITY DEFINER
COMMENT 'A Procedure' <--
SELECT CURRENT_DATE, RAND() FROM t //

  COMMENT 'A procedure'
  是一個可選的注釋說明。

  最后,注釋子句會跟過程定義存儲在一起。這個沒有固定的標準,我在文中會指出沒有固定標準的語句,不過幸運的是這些在我們標準的SQL中很少。

  6.
CREATE PROCEDURE p2 ()
LANGUAGE SQL
NOT DETERMINISTIC
SQL SECURITY DEFINER
COMMENT ''
SELECT CURRENT_DATE, RAND() FROM t //

  上面過程跟下面語句是等效的:
CREATE PROCEDURE p2 ()
SELECT CURRENT_DATE, RAND() FROM t //

  特征子句也有默認值,如果省略了就相當于:
LANGUAGE SQL NOT DETERMINISTIC SQL SECURITY DEFINER COMMENT ''

Digressions一些題外話

  Digression:
  調用p2()//的結果
mysql> call p2() //
+--------------+-----------------+
| CURRENT_DATE | RAND() |
+--------------+-----------------+
| 2004-11-09 | 0.7822275075896 |
+--------------+-----------------+
1 row in set (0.26 sec)
Query OK, 0 rows affected (0.26 sec)
  當調用過程p2時,一個SELECT語句被執行返回我們期望獲得的隨機數。
  Digression: sql_mode unchanging
  不會改變的

sql_mode
mysql> set sql_mode='ansi' //
mysql> create procedure p3()select'a'||'b'//
mysql> set sql_mode=''//
mysql> call p3()//
+------------+
| 'a' || 'b' |
+------------+
| ab |
+------------+

  MySQL在過程創建時會自動保持運行環境。例如:我們需要使用兩條豎線來連接字符串但是這只有在sql mode為ansi的時候才合法。如果我們將sql mode改為non-ansi,不用擔心,它仍然能工作,只要它第一次使用時能正常工作。

Exercise 練習

  Question
  問題
  如果你不介意練習一下的話,試能否不看后面的答案就能處理這些請求。
  創建一個過程,顯示`Hello world`。用大約5秒時間去思考這個問題,既然你已經學到了這里,這個應該很簡單。當你思考問題的時候,我們再隨機選擇一些剛才講過的東西復習:
  DETERMINISTIC
 ?。ù_定性)子句是反映輸出和輸入依賴特性的子句…調用過程使用CALL過程名(參數列表)方式。好了,我猜時間也到了。

  Answer
  答案
  好的,答案就是在過程體中包含
"SELECT 'Hello, world'"
  語句
  MySQL
mysql> CREATE PROCEDURE p4 () SELECT 'Hello, world' //
Query OK, 0 rows affected (0.00 sec)
mysql> CALL p4()//
+--------------+
| Hello, world |
+--------------+
| Hello, world |
+--------------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)

Parameters 參數

  讓我們更進一步的研究怎么在存儲過程中定義參數
  1. CREATE PROCEDURE p5
  () ...
  2. CREATE PROCEDURE p5
  ([IN] name data-type) ...
  3. CREATE PROCEDURE p5
  (OUT name data-type) ...
  4. CREATE PROCEDURE p5
  (INOUT name data-type) ...

  回憶一下前面講過的參數列表必須在存儲過程名后的括號中。上面的第一個例子中的參數列表是空的,第二個例子中有一個輸入參數。這里的詞IN可選,因為默認參數為IN(input)。

  第三個例子中有一個輸出參數,第四個例子中有一個參數,既能作為輸入也可以作為輸出。
  IN example 輸入的例子
mysql> CREATE PROCEDURE p5(p INT) SET @x = p //
Query OK, 0 rows affected (0.00 sec)
mysql> CALL p5(12345)//
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @x//
+-------+
| @x |
+-------+
| 12345 |
+-------+
1 row in set (0.00 sec)

  這個IN的例子演示的是有輸入參數的過程。在過程體中我將會話變量x設定為參數p的值。然后調用過程,將12345傳入參數p。選擇顯示會話變量@x,證明我們已經將參數值12345傳入。
  OUT example 輸出的例子
mysql> CREATE PROCEDURE p6 (OUT p INT)
-> SET p = -5 //
mysql> CALL p6(@y)//
mysql> SELECT @y//
+------+
| @y |
+------+
| -5 |
+------+

  這是另一個例子。這次的p是輸出參數,然后在過程調用中將p的值傳入會話變量@y中。

  在過程體中,我們給參數賦值-5,在調用后我們可以看出,OUT是告訴DBMS值是從過程中傳出的。
  同樣我們可以用語句
"SET @y = -5;"

  來達到同樣的效果

Compound Statements 復合語句

  現在我們展開的詳細分析一下過程體:
CREATE PROCEDURE p7 ()
BEGIN
SET @a = 5;
SET @b = 5;
INSERT INTO t VALUES (@a);
SELECT s1 * @a FROM t WHERE s1 >= @b;
END; // /* I won't CALL this.
這個語句將不會被調用
*/

  完成過程體的構造就是BEGIN/END塊。這個BEGIN/END語句塊和Pascal語言中的BEGIN/END是基本相同的,和C語言的框架是很相似的。我們可以使用塊去封裝多條語句。在這個例子中,我們使用了多條設定會話變量的語句,然后完成了一些insert和select語句。如果你的過程體中有多條語句,那么你就需要BEGIN/END塊了。BEGIN/END塊也被稱為復合語句,在這里你可以進行變量定義和流程控制。

  未完待續...


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 儋州市| 桐庐县| 兴海县| 广东省| 绥宁县| 松原市| 容城县| 安乡县| 金川县| 乌审旗| 永新县| 昌都县| 河间市| 景德镇市| 甘谷县| 神农架林区| 郸城县| 汝州市| 同江市| 岐山县| 浦城县| 武山县| 耒阳市| 班玛县| 贞丰县| 汤原县| 锦州市| 敦化市| 和平区| 新乡县| 香港 | 读书| 县级市| 兴义市| 望城县| 渭源县| 潢川县| 和龙市| 远安县| 花莲市| 襄垣县|