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 =
; //
MySQL的附加功能
任何數據操作語言的語句都將合法
CREATE PROCEDURE p () DROP TABLE t; //
MySQL擴充功能
直接的SELECT也是合法的
CREATE PROCEDURE p () SELECT
a
; //
順便提一下
我將存儲過程中包括DDL語句的功能稱為MySQL附加功能的原因是在SQL標准中把這個定義為非核心的
即可選組件
在過程體中有一個約束
就是不能有對例程或表操作的數據庫操作語句
例如下面的例子就是非法的
CREATE PROCEDURE p
()
CREATE PROCEDURE p
() DELETE FROM t; //
下面這些對MySQL
來說全新的語句
過程體中是非法的:
CREATE PROCEDURE
ALTER PROCEDURE
DROP PROCEDURE
CREATE FUNCTION
DROP FUNCTION
CREATE TRIGGER
DROP TRIGGER
不過你可以使用 CREATE PROCEDURE db
p
() DROP DATABASE db
//
但是類似 USE database
語句也是非法的
因為MySQL假定默認數據庫就是過程的工作場所
Call the Procedure 調用存儲過程
現在我們就可以調用一個存儲過程了
你所需要輸入的全部就是CALL和你過程名以及一個括號再一次強調
括號是必須的當你調用例子裡面的p
過程時
結果是屏幕返回了t表的內容
mysql> CALL p
() //
+
+
| s
|
+
+
|
|
+
+
row in set (
sec)
Query OK
rows affected (
sec)
因為過程中的語句是
SELECT * FROM t;
Let me say that again
another way
其他實現方式
mysql> CALL p
() //
和下面語句的執行效果一樣
mysql> SELECT * FROM t; //
所以
你調用p
過程就相當於你執行了下面語句
SELECT * FROM t;
好了
主要的知識點
創建和調用過程方法
已經清楚了
我希望你能對自己說這相當簡單
但是很快我們就有一系列的練習
每次都加一條子句
或者改變已經存在的子句
那樣在寫復雜部件前我們將會有很多可用的子句
Characteristics Clauses 特征子句
CREATE PROCEDURE p
()
LANGUAGE SQL <
NOT DETERMINISTIC <
SQL SECURITY DEFINER <
COMMENT
A Procedure
<
SELECT CURRENT_DATE
RAND() FROM t //
這裡我給出的是一些能反映存儲過程特性的子句
子句內容在括號之後
主體之前
這些子句都是可選的
他們有什麼作用呢?
CREATE PROCEDURE p
()
LANGUAGE SQL <
NOT DETERMINISTIC
SQL SECURITY DEFINER
COMMENT
A Procedure
SELECT CURRENT_DATE
RAND() FROM t //
很好
這個LANGUAGE SQL子句是沒有作用的
僅是為了說明下面過程的主體使用SQL語言編寫
這條是系統默認的
但你在這裡聲明是有用的
因為某些DBMS(IBM的DB
)需要它
如果你關注DB
的兼容問題最好還是用上
此外
今後可能會出現除SQL外的其他語言支持的存儲過程
CREATE PROCEDURE p
()
LANGUAGE SQL
NOT DETERMINISTIC <
SQL SECURITY DEFINER
COMMENT
A Procedure
SELECT CURRENT_DATE
RAND() FROM t //
下一個子句
NOT DETERMINISTIC
是傳遞給系統的信息
這裡一個確定過程的定義就是那些每次輸入一樣輸出也一樣的程序
在這個案例中
既然主體中含有SELECT語句
那返回肯定是未知的因此我們稱其NOT DETERMINISTIC
但是MySQL內置的優化程序不會注意這個
至少在現在不注意
CREATE PROCEDURE p
()
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)則是告訴服務器在這一步仍然要檢查調用者的權限
CREATE PROCEDURE p
()
LANGUAGE SQL
NOT DETERMINISTIC
SQL SECURITY DEFINER
COMMENT
A Procedure
<
SELECT CURRENT_DATE
RAND() FROM t //
COMMENT
A procedure
是一個可選的注釋說明
最後
注釋子句會跟過程定義存儲在一起
這個沒有固定的標准
我在文中會指出沒有固定標准的語句
不過幸運的是這些在我們標准的SQL中很少
CREATE PROCEDURE p
()
LANGUAGE SQL
NOT DETERMINISTIC
SQL SECURITY DEFINER
COMMENT
SELECT CURRENT_DATE
RAND() FROM t //
上面過程跟下面語句是等效的
CREATE PROCEDURE p
()
SELECT CURRENT_DATE
RAND() FROM t //
特征子句也有默認值
如果省略了就相當於
LANGUAGE SQL NOT DETERMINISTIC SQL SECURITY DEFINER COMMENT
Digressions一些題外話
Digression:
調用p
()//的結果
mysql> call p
() //
+
+
+
| CURRENT_DATE | RAND() |
+
+
+
|
|
|
+
+
+
row in set (
sec)
Query OK
rows affected (
sec)
當調用過程p
時
一個SELECT語句被執行返回我們期望獲得的隨機數
Digression: sql_mode unchanging
不會改變的
sql_mode
mysql> set sql_mode=
ansi
//
mysql> create procedure p
()select
a
||
b
//
mysql> set sql_mode=
//
mysql> call p
()//
+
+
|
a
||
b
|
+
+
| ab |
+
+
MySQL在過程創建時會自動保持運行環境
例如
我們需要使用兩條豎線來連接字符串但是這只有在sql mode為ansi的時候才合法
如果我們將sql mode改為non
ansi
不用擔心
它仍然能工作
只要它第一次使用時能正常工作
Exercise 練習 Question
問題
如果你不介意練習一下的話
試能否不看後面的答案就能處理這些請求
創建一個過程
顯示`Hello world`
用大約
秒時間去思考這個問題
既然你已經學到了這裡
這個應該很簡單
當你思考問題的時候
我們再隨機選擇一些剛才講過的東西復習
DETERMINISTIC
(確定性)子句是反映輸出和輸入依賴特性的子句…調用過程使用CALL過程名(參數列表)方式
好了
我猜時間也到了
Answer
答案
好的
答案就是在過程體中包含
SELECT
Hello
world
語句
MySQL
mysql> CREATE PROCEDURE p
() SELECT
Hello
world
//
Query OK
rows affected (
sec)
mysql> CALL p
()//
+
+
| Hello
world |
+
+
| Hello
world |
+
+
row in set (
sec)
Query OK
rows affected (
sec)
Parameters 參數 讓我們更進一步的研究怎麼在存儲過程中定義參數
CREATE PROCEDURE p
()
CREATE PROCEDURE p
([IN] name data
type)
CREATE PROCEDURE p
(OUT name data
type)
CREATE PROCEDURE p
(INOUT name data
type)
回憶一下前面講過的參數列表必須在存儲過程名後的括號中
上面的第一個例子中的參數列表是空的
第二個例子中有一個輸入參數
這裡的詞IN可選
因為默認參數為IN(input)
第三個例子中有一個輸出參數
第
From:http://tw.wingwit.com/Article/program/MySQL/201311/29319.html