MySQL 5.0 新特性教程是為需要了解 5.0 版本新特性的 MySQL 老用戶而寫(xiě)的。簡(jiǎn)單的來(lái)說(shuō)是介紹了“存儲(chǔ)過(guò)程、觸發(fā)器、視圖、信息架構(gòu)視圖”,在此感謝譯者陳朋奕的努力.
希望這本書(shū)能像內(nèi)行專家那樣與您進(jìn)行對(duì)話,用簡(jiǎn)單的問(wèn)題、例子讓你學(xué)到需要的知識(shí)。為了達(dá)到這樣的目的,我會(huì)從每一個(gè)細(xì)節(jié)開(kāi)始慢慢的為大家建立概念,最后會(huì)給大家展示較大的實(shí)用例,在學(xué)習(xí)之前也許大家會(huì)認(rèn)為這個(gè)用例很難,但是只要跟著課程去學(xué),相信很快就能掌握。
Conventions and Styles 約定和編程風(fēng)格
每次我想要演示實(shí)際代碼時(shí),我會(huì)對(duì) mysql 客戶端的屏幕就出現(xiàn)的代碼進(jìn)行調(diào)整,將字體改成 Courier,使他們看起來(lái)與普通文本不一樣。
在這里舉個(gè)例子:mysql> DROP FUNCTION f;Query OK, 0 rows affected (0.00 sec)
如果實(shí)例比較大,則需要在某些行和段落間加注釋,同時(shí)我會(huì)用將“<--”符號(hào)放在頁(yè)面的右邊以表示強(qiáng)調(diào)。
例如:
mysql> CREATE PROCEDURE p ()
-> BEGIN
-> /* This procedure does nothing */ <--
-> END;//Query OK, 0 rows affected (0.00 sec)
有時(shí)候我會(huì)將例子中的 "mysql>" 和 "->" 這些系統(tǒng)顯示去掉,你可以直接將代碼復(fù)制到 mysql 客戶端程序中(如果你現(xiàn)在所讀的不是電子版的,可以在 mysql.com 網(wǎng)站下載相關(guān)腳本)所以的例子都已經(jīng)在 Suse 9.2 Linux、Mysql 5.0.3 公共版上測(cè)試通過(guò)。
在您閱讀本書(shū)的時(shí)候,Mysql 已經(jīng)有更高的版本,同時(shí)能支持更多 OS 了,包括 Windows,Sparc,HP-UX。因此這里的例子將能正常的運(yùn)行在您的電腦上。但如果運(yùn)行仍然出現(xiàn)故障,可以咨詢你認(rèn)識(shí)的資深 Mysql 用戶,以得到長(zhǎng)久的支持和幫助。
A Definition and an Example 定義及實(shí)例
定義及實(shí)例存儲(chǔ)過(guò)程是一種存儲(chǔ)在書(shū)庫(kù)中的程序(就像正規(guī)語(yǔ)言里的子程序一樣),準(zhǔn)確的來(lái)說(shuō),MySQL支持的“routines(例程)”有兩種:一是我們說(shuō)的存儲(chǔ)過(guò)程,二是在其他 SQL 語(yǔ)句中可以返回值的函數(shù)(使用起來(lái)和 Mysql 預(yù)裝載的函數(shù)一樣,如 pi())。我在本書(shū)里面會(huì)更經(jīng)常使用存儲(chǔ)過(guò)程,因?yàn)檫@是我們過(guò)去的習(xí)慣,相信大家也會(huì)接受。
一個(gè)存儲(chǔ)過(guò)程包括名字,參數(shù)列表,以及可以包括很多 SQL 語(yǔ)句的 SQL 語(yǔ)句集。
在這里對(duì)局部變量,異常處理,循環(huán)控制和IF條件句有新的語(yǔ)法定義。
下面是一個(gè)包括存儲(chǔ)過(guò)程的實(shí)例聲明:(譯注:為了方便閱讀,此后的程序不添任何中文注釋)
CREATE PROCEDURE procedure1 /* name存儲(chǔ)過(guò)程名*/
(IN parameter1 INTEGER) /* parameters參數(shù)*/
BEGIN /* start of block語(yǔ)句塊頭*/
DECLARE variable1 CHAR(10); /* variables變量聲明*/
IF parameter1 = 17 THEN /* start of IF IF條件開(kāi)始*/
SET variable1 = ‘birds‘; /* assignment賦值*/
ELSE
SET variable1 = ‘beasts‘; /* assignment賦值*/
END IF; /* end of IF IF結(jié)束*/
INSERT INTO table1 valueS (variable1);/* statement SQL語(yǔ)句*/
END /* end of block語(yǔ)句塊結(jié)束*/
下面我將會(huì)介紹你可以利用存儲(chǔ)過(guò)程做的工作的所有細(xì)節(jié)。同時(shí)我們將介紹新的數(shù)據(jù)庫(kù)對(duì)象—觸發(fā)器,因?yàn)橛|發(fā)器和存儲(chǔ)過(guò)程的關(guān)聯(lián)是必然的。
Why Stored Procedures 為什么要用存儲(chǔ)過(guò)程
由于存儲(chǔ)過(guò)程對(duì)于 MySQL 來(lái)說(shuō)是新的功能,很自然的在使用時(shí)你需要更加注意。
畢竟,在此之前沒(méi)有任何人使用過(guò),也沒(méi)有很多大量的有經(jīng)驗(yàn)的用戶來(lái)帶你走他們走過(guò)的路。然而你應(yīng)該開(kāi)始考慮把現(xiàn)有程序(可能在服務(wù)器應(yīng)用程序中,用戶自定義函數(shù)(UDF)中,或是腳本中)轉(zhuǎn)移到存儲(chǔ)過(guò)程中來(lái)。這樣做不需要原因,你不得不去做。
因?yàn)榇鎯?chǔ)過(guò)程是已經(jīng)被認(rèn)證的技術(shù)!雖然在Mysql中它是新的,但是相同功能的函數(shù)在其他DBMS中早已存在,而它們的語(yǔ)法往是相同的。因此你可以從其他人那里獲得這些概念,也有很多你可以咨詢或者雇用的經(jīng)驗(yàn)用戶,還有許多第三方的文檔可供你閱讀。
存儲(chǔ)過(guò)程會(huì)使系統(tǒng)運(yùn)行更快!雖然我們暫時(shí)不能在 Mysql 上證明這個(gè)優(yōu)勢(shì),用戶得到的體驗(yàn)也不一樣。我們可以說(shuō)的就是 Mysql 服務(wù)器在緩存機(jī)制上做了改進(jìn),就像 Preparedstatements(預(yù)處理語(yǔ)句)所做的那樣。由于沒(méi)有編譯器,因此 SQL 存儲(chǔ)過(guò)程不會(huì)像外部語(yǔ)言(如C)編寫(xiě)的程序運(yùn)行起來(lái)那么快。但是提升速度的主要方法卻在于能否降低網(wǎng)絡(luò)信息流量。如果你需要處理的是需要檢查、循環(huán)、多語(yǔ)句但沒(méi)有用戶交互的重復(fù)性任務(wù),你就可以使用保存在服務(wù)器上的存儲(chǔ)過(guò)程來(lái)完成。這樣在執(zhí)行任務(wù)的每一步時(shí)服務(wù)器和客戶端之間就沒(méi)那么多的信息來(lái)往了。
所以存儲(chǔ)過(guò)程是可復(fù)用的組件!想象一下如果你改變了主機(jī)的語(yǔ)言,這對(duì)存儲(chǔ)過(guò)程不會(huì)產(chǎn)生影響,因?yàn)樗菙?shù)據(jù)庫(kù)邏輯而不是應(yīng)用程序。存儲(chǔ)過(guò)程是可以移植的!當(dāng)你用SQL編寫(xiě)存儲(chǔ)過(guò)程時(shí),你就知道它可以運(yùn)行在Mysql 支持的任何平臺(tái)上,不需要你額外添加運(yùn)行環(huán)境包,也不需要為程序在操作系統(tǒng)中執(zhí)行設(shè)置許可,或者為你的不同型號(hào)的電腦存儲(chǔ)過(guò)程將被保存!如果你編寫(xiě)好了一個(gè)程序,例如顯示銀行事物處理中的支票撤消,那想要了解支票的人就可以找到你的程序。
它會(huì)以源代碼的形式保存在數(shù)據(jù)庫(kù)中。這將使數(shù)據(jù)和處理數(shù)據(jù)的進(jìn)程有意義的關(guān)聯(lián)這可能跟你在課上聽(tīng)到的規(guī)劃論中說(shuō)的一樣。存儲(chǔ)過(guò)程可以遷移!
Mysql 完全支持 SQL 2003 標(biāo)準(zhǔn)。某些數(shù)據(jù)庫(kù)(如 DB2、Mimer)同樣支持。但也有部分不支持的,如Oracle、SQL Server 不支持。我們將會(huì)給予足夠幫助和工具,使為其他 DBMS 編寫(xiě)的代碼能更容易轉(zhuǎn)移到Mysql 上。
Setting up with MySQL 5.0 設(shè)置并開(kāi)始 MySQL 5.0 服務(wù)
通過(guò) mysql_fix_privilege_tables 或者 ~/mysql-5.0/scripts/mysql_install_db 來(lái)開(kāi)始MySQL服務(wù)。
作為我們練習(xí)的準(zhǔn)備工作的一部分,我假定 MySQL 5.0 已經(jīng)安裝。如果沒(méi)有數(shù)據(jù)庫(kù)管理員為你安裝好數(shù)據(jù)庫(kù)以及其他軟件,你就需要自己去安裝了。不過(guò)你很容易忘掉一件事,那就是你需要有一個(gè)名為 mysql.proc 的表。
在安裝了最新版本后,你必須運(yùn)行 mysql_fix_privilege_tables 或者 mysql_install_db。
?。ㄖ恍枰\(yùn)行其中一個(gè)就夠了)——不然存儲(chǔ)過(guò)程將不能工作。我同時(shí)啟用在root身份后運(yùn)行一個(gè)非正式的SQL腳本,如下:
mysql>source/home/pgulutzan/mysql-5.0/scripts/mysql_prepare_privilege_tables_for_5.sql
Starting the MySQL Client 啟動(dòng) MySQL 客戶端
這是我啟動(dòng)mysql客戶端的方式。你也許會(huì)使用其他方式,如果你使用的是二進(jìn)制版本或者是 Windows 系統(tǒng)的電腦,你可能會(huì)在其他子目錄下運(yùn)行以下程序:
easy@phpv:~> /usr/local/mysql/bin/mysql --user=root
Welcome to the MySQL monitor. Commands end with or \g.
Your MySQL connection id is 1 to server version: 5.0.3-alpha-debug
Type ‘help;‘ or ‘\h‘ for help. Type ‘\c‘ to clear the buffer.
在演示中,我將會(huì)展示以 root 身份登陸后的 mysql 客戶端返回的結(jié)果,這樣意味著我有極大的特權(quán)。
Check for the Correct Version 核對(duì)版本
為了確認(rèn)使用的 MySQL 的版本是正確的,我們要查詢版本。我有兩種方法確認(rèn)我使用的是 5.0 版本:
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)
當(dāng)看見(jiàn)數(shù)字 ‘5.0.x‘ 后就可以確認(rèn)存儲(chǔ)過(guò)程能夠在這個(gè)客戶端上正常工作。
The Sample "Database" 示例數(shù)據(jù)庫(kù)
現(xiàn)在要做的第一件事是創(chuàng)建一個(gè)新的數(shù)據(jù)庫(kù)然后設(shè)定為默認(rèn)數(shù)據(jù)庫(kù)實(shí)現(xiàn)這個(gè)步驟的 SQL 語(yǔ)句如下:
CREATE DATABASE db5;
USE db5;
例如:
mysql> CREATE DATABASE db5;
Query OK, 1 row affected (0.00 sec)
mysql> USE db5;
Database changed
在這里要避免使用有重要數(shù)據(jù)的實(shí)際的數(shù)據(jù)庫(kù)然后我們創(chuàng)建一個(gè)簡(jiǎn)單的工作表。
實(shí)現(xiàn)這個(gè)步驟的 SQL 語(yǔ)句如下:
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)
你會(huì)發(fā)現(xiàn)我只在表中插入了一列。這樣做的原因是我要保持表的簡(jiǎn)單,因?yàn)樵谶@里并不需要展示查詢數(shù)據(jù)的技巧,而是教授存儲(chǔ)過(guò)程,不需要使用大的數(shù)據(jù)表,因?yàn)樗旧硪呀?jīng)夠復(fù)雜了。
這就是示例數(shù)據(jù)庫(kù),我們將從這個(gè)名字為 t 的只包含一列的表開(kāi)始 Pick a Delimiter 選擇分隔符
現(xiàn)在我們需要一個(gè)分隔符,實(shí)現(xiàn)這個(gè)步驟的SQL語(yǔ)句如下:
DELIMITER //
例如:
mysql> DELIMITER //
分隔符是你通知 mysql 客戶端你已經(jīng)完成輸入一個(gè) SQL 語(yǔ)句的字符或字符串符號(hào)。一直以來(lái)我們都使用分號(hào)“;”,但在存儲(chǔ)過(guò)程中,這會(huì)產(chǎn)生不少問(wèn)題,因?yàn)榇鎯?chǔ)過(guò)程中有許多語(yǔ)句,所以每一個(gè)都需要一個(gè)分號(hào)因此你需要選擇一個(gè)不太可能出現(xiàn)在你的語(yǔ)句或程序中的字符串作為分隔符。
我曾用過(guò)雙斜杠“//”,也有人用豎線“|”。我曾見(jiàn)過(guò)在 DB2 程序中使用“@”符號(hào)的,但我不喜歡這樣。你可以根據(jù)自己的喜好來(lái)選擇,但是在這個(gè)課程中為了更容易理解,你最好選擇跟我一樣。如果以后要恢復(fù)使用“;”(分號(hào))作為分隔符,輸入下面語(yǔ)句就可以了:
"DELIMITER //".
CREATE PROCEDURE Example 創(chuàng)建程序?qū)嵗?br>
CREATE PROCEDURE p1 () SELECT * FROM t; //
也許這是你使用 Mysql 創(chuàng)建的第一個(gè)存儲(chǔ)過(guò)程。假如是這樣的話,最好在你的日記中記下這個(gè)重要的里程碑。
CREATE PROCEDURE p1 () SELECT * FROM t; // <--
SQL 語(yǔ)句存儲(chǔ)過(guò)程的第一部分是“CREATE PROCEDURE”:
CREATE PROCEDURE p1 () SELECT * FROM t; // <--
第二部分是過(guò)程名,上面新存儲(chǔ)過(guò)程的名字是p1。
Digression: Legal Identifiers 題外話:合法標(biāo)識(shí)符的問(wèn)題
存儲(chǔ)過(guò)程名對(duì)大小寫(xiě)不敏感,因此‘P1’和‘p1’是同一個(gè)名字,在同一個(gè)數(shù)據(jù)庫(kù)中你將不能給兩個(gè)存儲(chǔ)過(guò)程取相同的名字,因?yàn)檫@樣將會(huì)導(dǎo)致重載。某些 DBMS 允許重載(Oracle支持),但是 MySQL 不支持(譯者話:希望以后會(huì)支持吧。)。
你可以采取“數(shù)據(jù)庫(kù)名.存儲(chǔ)過(guò)程名”這樣的折中方法,如“db5.p1”。存儲(chǔ)過(guò)程名可以分開(kāi),它可以包括空格符,其長(zhǎng)度限制為64個(gè)字符,但注意不要使用 MySQL 內(nèi)建函數(shù)的名字,如果這樣做了,在調(diào)用時(shí)將會(huì)出現(xiàn)下面的情況:
mysql> CALL pi();
Error 1064 (42000): You have a syntax error.
mysql> CALL pi ();
Error 1305 (42000): PROCEDURE does not exist.
在上面的第一個(gè)例子里,我調(diào)用的是一個(gè)名字叫 pi 的函數(shù),但你必須在調(diào)用的函數(shù)名后加上空格,就像第二個(gè)例子那樣。
CREATE PROCEDURE p1 () SELECT * FROM t; // <--
其中“()”是“參數(shù)列表”。
CREATE PROCEDURE
語(yǔ)句的第三部分是參數(shù)列表。通常需要在括號(hào)內(nèi)添加參數(shù)。例子中的存儲(chǔ)過(guò)程沒(méi)有參數(shù),因此參數(shù)列表是空的—所以我只需要鍵入空括號(hào),然而這是必須的。
CREATE PROCEDURE p1 () SELECT * FROM t; // <--
"SELECT * FROM t;"
是存儲(chǔ)過(guò)程的主體。
然后到了語(yǔ)句的最后一個(gè)部分了,它是存儲(chǔ)過(guò)程的主體,是一般的SQL語(yǔ)句。過(guò)程體中語(yǔ)句
"SELECT * FROM t;"
包含一個(gè)分號(hào),如果后面有語(yǔ)句結(jié)束符號(hào)(//)時(shí)可以不寫(xiě)這個(gè)分號(hào)。
如果你還記得我把這部分叫做程序的主體將會(huì)是件好事,因?yàn)椋╞ody)這個(gè)詞是大家使用的技術(shù)上的術(shù)語(yǔ)。通常我們不會(huì)將 SELECT 語(yǔ)句用在存儲(chǔ)過(guò)程中,這里只是為了演示。所以使用這樣的語(yǔ)句,能在調(diào)用時(shí)更好的看出程序是否正常工作?!?br>
(本文已被瀏覽 952 次)
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)
點(diǎn)擊舉報(bào)。