最大的網站源碼資源下載站,
introduction 簡介
mysql 5.0 新特性教程是為需要了解5.0版本新特性的mysql老用戶而寫的。簡單的來說是介紹了“存儲過程、觸發器、視圖、信息架構視圖”,在此感謝譯者陳朋奕的努力.
希望這本書能像內行專家那樣與您進行對話,用簡單的問題、例子讓你學到需要的知識。為了達到這樣的目的,我會從每一個細節開始慢慢的為大家建立概念,最后會給大家展示較大的實用例,在學習之前也許大家會認為這個用例很難,但是只要跟著課程去學,相信很快就能掌握。
conventions and styles 約定和編程風格
每次我想要演示實際代碼時,我會對mysql客戶端的屏幕就出現的代碼進行調整,將字體改成courier,使他們看起來與普通文本不一樣。
在這里舉個例子:mysql> drop function f;query ok, 0 rows affected (0.00 sec)
如果實例比較大,則需要在某些行和段落間加注釋,同時我會用將“<--”符號放在頁面的右邊以表示強調。
例如:
mysql> create procedure p ()
-> begin
-> /* this procedure does nothing */ <--
-> end;//query ok, 0 rows affected (0.00 sec)
有時候我會將例子中的"mysql>"和"->"這些系統顯示去掉,你可以直接將代碼復制到mysql客戶端程序中(如果你現在所讀的不是電子版的,可以在mysql.com網站下載相關腳本)所以的例子都已經在suse 9.2 linux、mysql 5.0.3公共版上測試通過。
在您閱讀本書的時候,mysql已經有更高的版本,同時能支持更多os了,包括windows,sparc,hp-ux。因此這里的例子將能正常的運行在您的電腦上。但如果運行仍然出現故障,可以咨詢你認識的資深mysql用戶,以得到長久的支持和幫助。
a definition and an example 定義及實例
定義及實例存儲過程是一種存儲在書庫中的程序(就像正規語言里的子程序一樣),準確的來說,mysql支持的“routines(例程)”有兩種:一是我們說的存儲過程,二是在其他sql語句中可以返回值的函數(使用起來和mysql預裝載的函數一樣,如pi())。我在本書里面會更經常使用存儲過程,因為這是我們過去的習慣,相信大家也會接受。
一個存儲過程包括名字,參數列表,以及可以包括很多sql語句的sql語句集。
在這里對局部變量,異常處理,循環控制和if條件句有新的語法定義。
下面是一個包括存儲過程的實例聲明:(譯注:為了方便閱讀,此后的程序不添任何中文注釋)
create procedure procedure1 /* name存儲過程名*/
(in parameter1 integer) /* parameters參數*/
begin /* start of block語句塊頭*/
declare variable1 char(10); /* variables變量聲明*/
if parameter1 = 17 then /* start of if if條件開始*/
set variable1 = 'birds'; /* assignment賦值*/
else
set variable1 = 'beasts'; /* assignment賦值*/
end if; /* end of if if結束*/
insert into table1 values (variable1);/* statement sql語句*/
end /* end of block語句塊結束*/
下面我將會介紹你可以利用存儲過程做的工作的所有細節。同時我們將介紹新的數據庫對象—觸發器,因為觸發器和存儲過程的關聯是必然的。
why stored procedures 為什么要用存儲過程
由于存儲過程對于mysql來說是新的功能,很自然的在使用時你需要更加注意。
畢竟,在此之前沒有任何人使用過,也沒有很多大量的有經驗的用戶來帶你走他們走過的路。然而你應該開始考慮把現有程序(可能在服務器應用程序中,用戶自定義函數(udf)中,或是腳本中)轉移到存儲過程中來。這樣做不需要原因,你不得不去做。
show variables like 'version';
or
select version();
例如:
mysql> show variables like 'version';
+---------------+-------------------+
| variable_name | value |
+---------------+-------------------+
| version | 5.0.3-alpha-debug |
+---------------+-------------------+
1 row in set (0.00 sec)
mysql> select version();
+-------------------+
| version() |
+-------------------+
| 5.0.3-alpha-debug |
+-------------------+
1 row in set (0.00 sec)當看見數字'5.0.x' 后就可以確認存儲過程能夠在這個客戶端上正常工作。
the sample "database" 示例數據庫
現在要做的第一件事是創建一個新的數據庫然后設定為默認數據庫實現這個步驟的sql語句如下:
create database db5;
use db5;
例如:
mysql> create database db5;
query ok, 1 row affected (0.00 sec)
mysql> use db5;
database changed
在這里要避免使用有重要數據的實際的數據庫然后我們創建一個簡單的工作表。
實現這個步驟的sql語句如下:
mysql> create database db5;
query ok, 1 row affected (0.01 sec)
mysql> use db5;
database changed
mysql> create table t (s1 int);
query ok, 0 rows affected (0.01 sec)
mysql> insert into t values (5);
query ok, 1 row affected (0.00 sec)
你會發現我只在表中插入了一列。這樣做的原因是我要保持表的簡單,因為在這里并不需要展示查詢數據的技巧,而是教授存儲過程,不需要使用大的數據表,因為它本身已經夠復雜了。
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)則是告訴服務器在這一步仍然要檢查調用者的權限。
商業源碼熱門下載www.html.org.cn
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)。
the new sql statements 新sql語
新聞熱點
疑難解答