欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
MySQL數據庫技術(shù)(04)
破釜沉舟 http://www.7880.com
MySQL數據庫技術(shù)(04)
文章類(lèi)別:MySQL  發(fā)表日期:2005-09-23     
閱讀次數: 474
現在我們已經(jīng)具備了所需的所有基礎知識;可以將MySQL 投入工作了!本節提供一個(gè)教程,幫助熟悉M y S Q L。在完成這個(gè)教程時(shí),將創(chuàng )建一個(gè)樣例數據庫和這個(gè)數據庫中的表,然后增加、檢索、刪除和修改信息與數據庫進(jìn)行交互。此外,在操作這個(gè)樣例數據庫的過(guò)程中,將能學(xué)到下列東西:
■ 如何利用mysql 客戶(hù)機程序與MySQL 通信。
■ SQL 語(yǔ)言的基本語(yǔ)句。(如果您曾經(jīng)使用過(guò)其他R D B M S,從而熟悉S Q L,那么瀏覽一下這個(gè)教程,看看SQL 的MySQL 版與您熟悉的版本有何差別也是很好的。)正如上一節所述, MySQL 采用客戶(hù)機/服務(wù)器體系結構,其中服務(wù)器運行在存放數據庫的機器上,而客戶(hù)機通過(guò)網(wǎng)絡(luò )連接到服務(wù)器。這個(gè)教程主要基于mysql 客戶(hù)機的應用。m y s q l讀取您的SQL 查詢(xún),將它們發(fā)送給服務(wù)器,并顯示結果。mysql 運行在MySQL 所支持的所有平臺上,并提供與服務(wù)器交互的最直接的手段,因此,它首先是一個(gè)邏輯上的客戶(hù)機。
在本書(shū)中,我們將用samp_db 作為樣例數據庫的名稱(chēng)。但是有可能在您完成本例子的過(guò)程中需要使用另一個(gè)數據庫名。因為可能在您的系統上已經(jīng)有某個(gè)人使用了samp_db 這個(gè)名稱(chēng),或者管理員給您指定了另一個(gè)數據庫名稱(chēng)。在后面的例子中,無(wú)論是哪種情況,都用數
據庫的實(shí)際名稱(chēng)代替s a m p _ d b。表名可以像例子所顯示的那樣精確地使用,即使系統中的多個(gè)人都具有他們自己的樣例數據庫也是如此。順便說(shuō)一下,在MySQL 中,如果有人使用了相同的表名也沒(méi)什么關(guān)系。一旦各個(gè)用戶(hù)都具有自己的數據庫, MySQL 將一直保留這些數據庫名,防止各用戶(hù)互相干擾。
1.4.1 基本要求
為了試驗這個(gè)教程中的例子,必須安裝M y S Q L。特別是必須具有對MySQL 客戶(hù)機和某個(gè)MySQL 服務(wù)器的訪(fǎng)問(wèn)權。相應的客戶(hù)機程序必須位于您的機器上。至少需要有m y s q l程序,最好還有m y s q l i m p o r t程序。服務(wù)器也可以位于您的機器上,盡管這不是必須的。實(shí)際上,只要允許連接到服務(wù)器,那么服務(wù)器位于何位置都沒(méi)有關(guān)系。若服務(wù)器正巧運行在您的機器上,適當的客戶(hù)機程序又已經(jīng)安裝,那么就可以開(kāi)始試驗了。如果您尚需設法搞到M y S Q L,可參閱附錄A“獲得和安裝軟件”的說(shuō)明。如果您正自己安裝M y S Q L,可參閱這一章,或把它給管理員看。如果網(wǎng)絡(luò )訪(fǎng)問(wèn)是通過(guò)一個(gè)因特網(wǎng)服務(wù)商(I S P)進(jìn)行的,那么可查看該服務(wù)商是否擁有M y S Q L。如果該ISP 不提供MySQL 服務(wù),可查看附錄J“因特網(wǎng)服務(wù)商”以得到某些選擇更適合的服務(wù)商的建議。
除M y S Q L軟件外,還需要得到創(chuàng )建樣例數據庫及其表的權限。如果您沒(méi)有這種權限,可以向MySQL 管理員咨詢(xún)。管理員可通過(guò)運行mysql 并發(fā)布如下的命令提供這種權限:
MySQL 與mysql 的區別
為了避免混淆,應該說(shuō)明,“M y S Q L”指的是整個(gè)MySQL RDBMS,而“m y s q l”代表的是一個(gè)特定的客戶(hù)機程序名。它們的發(fā)音都是相同的,但可通過(guò)不同的大小寫(xiě)字符和字體來(lái)區分。關(guān)于發(fā)音,MySQL 的發(fā)音為“m y - e s s - q u e u e - e l l”。我們知道這是因為MySQL 參考指南中是這樣發(fā)音的。而SQL 的發(fā)音為“s e q u e l”或“e s s - q u e u e - e l l”。我不認為哪個(gè)發(fā)音更好一些。愿意讀哪個(gè)音都可以,不過(guò)在您對別人讀的時(shí)候,他可能會(huì )用他認為是“正確”的發(fā)音對您進(jìn)行糾正。
前一個(gè)命令在paul 從l o c a l h o s t(服務(wù)器運行在正運行的同一主機)連接時(shí),允許它完全訪(fǎng)問(wèn)samp_db 數據庫及它的所有表。它還給出了一個(gè)口令s e c r e t。第二個(gè)命令與第一個(gè)類(lèi)似,但允許paul 從任何主機上連接(“%”為通配符)。也可以用特定的主機名取代“%”,使p a u l只能從該主機上進(jìn)行連接。(如果您的服務(wù)器允許從localhost 匿名訪(fǎng)問(wèn),由于服務(wù)器搜索授權表查找輸入連接匹配的方式的原因,這樣一個(gè)GRANT 語(yǔ)句可能是必須的。)關(guān)于G R A N T語(yǔ)句以及設置MySQL 用戶(hù)賬號的更詳細信息,可在第11 章“常規的MySQL 管理”找到。
1.4.2 取得樣例數據庫的分發(fā)包
這個(gè)教程在某些地方要涉及來(lái)自“樣例數據庫分發(fā)包”中的文件。有的文件含有幫助來(lái)設置樣例數據庫的查詢(xún)或數據。為了得到這個(gè)分發(fā)包,可參閱附錄A。在打開(kāi)這個(gè)分發(fā)包時(shí),將創(chuàng )建一個(gè)名為samp_db 的目錄,此目錄中含有所需的文件。無(wú)論您在哪個(gè)地方試驗與樣例數據庫有關(guān)的例子,建議都移入該目錄。
1.4.3 建立和中止與服務(wù)器的連接
為了連接到服務(wù)器,從外殼程序(即從UNIX 提示符,或從Windows 下的DOS 控制臺)激活mysql 程序。命令如下:
其中的“%”在本書(shū)中代表外殼程序提示符。這是UNIX 標準提示符之一;另一個(gè)為“$”。在Windows 下,提示符類(lèi)似“c : \ >”。
mysql 命令行的options 部分可能是空的,但更可能的是發(fā)布一條類(lèi)似如下的命令:
在激活mysql 時(shí),有可能不必提供所有這些選項;確切使用的命令請咨詢(xún)MySQL 管理員。此外,可能還需要至少指定一個(gè)名稱(chēng)和一個(gè)口令。
在剛開(kāi)始學(xué)習MySQL 時(shí),大概會(huì )為其安全系統而煩惱,因為它使您難于做自己想做的事。(您必須取得創(chuàng )建和訪(fǎng)問(wèn)數據庫的權限,任何時(shí)候連接到數據庫都必須給出自己的名字和口令。)但是,在您通過(guò)數據庫錄入和使用自己的記錄后,看法就會(huì )馬上改變了。這時(shí)您會(huì )很欣賞MySQL 阻止了其他人窺視(或者更惡劣一些,破壞?。┠馁Y料。
下面介紹選項的含義:
■ - h h o s t _ n a m e(可選擇形式:- - h o s t =h o s t _ n a m e)
希望連接的服務(wù)器主機。如果此服務(wù)器運行在與mysql 相同的機器上,這個(gè)選項一般可
省略。
■ -u u s e r _ n a m e(可選擇的形式:- - u s e r =u s e r _ n a m e)您的MySQL 用戶(hù)名。如果使用UNIX 且您的MySQL 用戶(hù)名與注冊名相同,則可以省去這個(gè)選項;mysql 將使用您的注冊名作為您的MySQL 名。在Windows 下,缺省的用戶(hù)名為O D B C。這可能不一定非常有用??稍诿钚猩现付ㄒ粋€(gè)名字,也可以通過(guò)設置USER 變量在環(huán)境變量中設置一個(gè)缺省名。如用下列set 命令指定paul 的一個(gè)用戶(hù)名:
■ - p(可選擇的形式:- - p a s s w o r d)
這個(gè)選項告訴mysql 提示鍵入您的MySQL 口令。注意:可用-pyour_password 的形式(可選擇的形式: - - p a s s w o r d = y o u r _ p a s s w o r d)在命令行上鍵入您的口令。但是,出于安全的考慮,最好不要這樣做。選擇-p 不跟口令告訴mysql 在啟動(dòng)時(shí)提示您鍵入口令。例如:
在看到Enter password: 時(shí),鍵入口令即可。(口令不會(huì )顯到屏幕,以免給別人看到。)請注意,MySQL 口令不一定必須與UNIX 或Windows 口令相同。如果完全省略了-p 選項,mysql 就認為您不需要口令,不作提示。請注意: -h 和-u 選項與跟在它們后面的詞有關(guān),無(wú)論選項和后跟的詞之間是否有空格。而-p 卻不是這樣,如果在命令行上給出口令, -p 和口令之間一定不加空格。例如,假定我的MySQL 用戶(hù)名和口令分別為paul 和s e c r e t,希望連接到在我注冊的同一機器上運行的服務(wù)器上。下面的mysql 命令能完成這項工作:
在我鍵入命令后, mysql 顯示Enter password: 提示鍵入口令。然后我鍵入口令( * * * * * *表明我鍵入了s e c r e t)。如果一切順利的話(huà), mysql 顯示一串消息和一個(gè)“ m y s q l >”提示,表示它正等待我發(fā)布查詢(xún)。完整的啟動(dòng)序列如下所示:
為了連接到在其他某個(gè)機器上運行的服務(wù)器,需要用-h 指定主機名。如果該主機為pit -v i p e r. s n a k e . n e t,則相應的命令如下所示:
在后面的說(shuō)明mysql 命令行的多數例子中,為簡(jiǎn)單起見(jiàn),我們打算省去- h、-u 和-p 選項。并且假定您將會(huì )提供任何所需的選項。
有很多設置賬號的方法,從而不必在每次運行mysql 時(shí)都在連接參數中進(jìn)行鍵入。這個(gè)問(wèn)題在1 . 5節“與mysql 交互的技巧”中介紹。您可能會(huì )希望現在就跳到該節,以便找到一些更易于連接到服務(wù)器的辦法。
在建立了服務(wù)器的一個(gè)連接后,可在任何時(shí)候鍵入下列命令來(lái)結束會(huì )話(huà):
還可以鍵入Control-D 來(lái)退出,至少在UNIX 上可以這樣。
1.4.4 發(fā)布查詢(xún)
在連接到服務(wù)器后,就可以發(fā)布查詢(xún)了。本節介紹有關(guān)與mysql 交互應該了解的一些知識。為了在mysql 中輸入一個(gè)查詢(xún),只需鍵入它即可。在查詢(xún)的結尾處,鍵入一個(gè)分號(“;”)并按Enter 鍵。分號告訴mysql 該查詢(xún)是完整的。(如果您喜歡鍵入兩個(gè)字符的話(huà),也可以使用“\ g”終止查詢(xún)。)在鍵入一個(gè)查詢(xún)之后, mysql 將其發(fā)送到服務(wù)器上。該服務(wù)器處理此查詢(xún)并將結果送回m y s q l,mysql 將此結果顯示出來(lái)。下面是一個(gè)簡(jiǎn)單的查詢(xún)例子和結果:
它給出當前的日期和時(shí)間。(NOW() 函數本身并無(wú)多大用處,但可將其用于表達式中。如比較當前日期和其他日期的差異。)
mysql 還在結果中顯示行數計數。本書(shū)在例子中一般不給出這個(gè)計數。因為mysql 需要見(jiàn)到分號才發(fā)送查詢(xún)到服務(wù)器,所以在單一的行上不需要鍵入分號。如果有必要,可將一個(gè)查詢(xún)分為幾行,如下所示:
請注意,在鍵入查詢(xún)的第一行后,提示符從‘m y s q l’ 變成了‘- >’;這表示mysql 允許繼續鍵入這個(gè)查詢(xún)。這是一個(gè)重要的提示,因為如果在查詢(xún)的末尾忘記了分號,此提示將有助于提醒您查詢(xún)尚不完整。否則您會(huì )一直等下去,心里納悶為什么mysql 執行查詢(xún)?yōu)槭裁催@么長(cháng)的時(shí)間還沒(méi)完;而mysql 也搞不清為什么結束查詢(xún)的鍵入要花您那么多的時(shí)間!
大部分情況下,用大寫(xiě)字符、小寫(xiě)字符或大小寫(xiě)字符混合鍵入查詢(xún)沒(méi)什么關(guān)系。下列查詢(xún)全是等價(jià)的:
本書(shū)中的例子用大寫(xiě)字符表示SQL 關(guān)鍵字和函數名,用小寫(xiě)字符表示數據庫、表和列名。
如果在查詢(xún)中調用一個(gè)函數,在函數名和后跟的圓括號中間不允許有空格,例:
這兩個(gè)查詢(xún)看上去差別不大,但第二個(gè)失敗了,因為圓括號并沒(méi)有緊跟在函數名的后面。如果已經(jīng)開(kāi)始鍵入一個(gè)多行的查詢(xún),而又不想立即執行它,可鍵入‘\ c’ 來(lái)跳過(guò)(放棄)它,如:
請注意,提示符又變回了‘m y s q l >’,這表示mysql 為鍵入的新查詢(xún)作好了準備??蓪⒉樵?xún)存儲在一個(gè)文件中并告訴mysql 從文件中讀取查詢(xún)而不是等待鍵盤(pán)輸入??衫猛鈿こ绦蜴I入重定向實(shí)用程序來(lái)完成這項工作。例如,如果在文件my_file.sql 中存放有查
詢(xún),可如下執行這些查詢(xún):
可用這種辦法調用任何所需的文件。這里用后綴為“ . s q l”來(lái)表示該文件含有SQL 語(yǔ)句。執行mysql 的這種方法將在輸入數據到samp_db 數據庫時(shí)的“增加新記錄”中使用。為了裝載一個(gè)表,讓mysql 從某個(gè)文件中讀取I N S E RT 語(yǔ)句比每次用手工鍵入這些語(yǔ)句更為方便。
本教程的其余部分向您提供了許多可以自己試試的查詢(xún)。這些查詢(xún)以‘m y s q l >’ 提示為前導后跟結束分號,這些例子通常都給出了查詢(xún)輸出結果??梢园唇o出的形式鍵入這些查詢(xún),所得到的結果應該與自學(xué)材料中的相同。給出的查詢(xún)中無(wú)提示符的或無(wú)分號語(yǔ)句結束符的只是用來(lái)說(shuō)明某個(gè)要點(diǎn),不用執行它們。(如果愿意您可以試一下,但如果試的話(huà),請記住給語(yǔ)句末尾加一個(gè)分號。)本書(shū)后面的章節中,我們一般不給出‘m y s q l >’ 提示或SQL 語(yǔ)句的分號。這樣做的原因是為了可以在非mysql 客戶(hù)機程序的語(yǔ)言環(huán)境(如在Perl 腳本中或PHP 腳本中)中發(fā)布查詢(xún),在這些語(yǔ)言環(huán)境中,既無(wú)提示符也不需要分號。在專(zhuān)門(mén)針對mysql 輸入一個(gè)查詢(xún)的場(chǎng)合會(huì )作出相應的說(shuō)明。
1.4.5 創(chuàng )建數據庫
現在開(kāi)始創(chuàng )建samp_db 樣例數據庫及其表,填充這些表并對包含在這些表中的數據進(jìn)行一些簡(jiǎn)單的查詢(xún)。
使用數據庫涉及幾個(gè)步驟:
1) 創(chuàng )建(初始化)數據庫。
2) 創(chuàng )建數據庫中的表。
3) 對表進(jìn)行數據插入、檢索、修改或刪除。
檢索現有數據是對數據庫執行的最簡(jiǎn)單且常見(jiàn)的操作。另外幾個(gè)最簡(jiǎn)單且常見(jiàn)的操作是插入新數據、更新或刪除現有數據。較少使用的操作是創(chuàng )建表的操作,而最不常用的操作是創(chuàng )建數據庫。
我們將從頭開(kāi)始,先創(chuàng )建數據庫,再插入數據,然后對數據進(jìn)行檢索。為了創(chuàng )建一個(gè)新的數據庫,用mysql 連接到數據庫然后發(fā)布C R E ATE DATABASE 語(yǔ)句,此語(yǔ)句指定了數據庫名:
在創(chuàng )建表以及對這些表進(jìn)行各種操作之前,必須先創(chuàng )建samp_db 數據庫。創(chuàng )建數據庫后,這個(gè)新創(chuàng )建的數據庫并不是當前數據庫。這可從執行下面的查詢(xún)看出:
為了使samp_db 成為當前數據庫,發(fā)布USE 語(yǔ)句即可:
USE 為少數幾個(gè)不需要終結符的語(yǔ)句之一,當然,加上終結符也不會(huì )出錯。HELP 是另一個(gè)不需要終結符的語(yǔ)句。如果想了解不需要終結符的語(yǔ)句有哪些,可發(fā)布HELP 語(yǔ)句。在發(fā)布了USE 語(yǔ)句后,samp_db 成為缺省數據庫:
使數據庫成為當前數據庫的另一個(gè)方法是在激活mysql 時(shí)在命令行上指定它,如下所示:
事實(shí)上,這是一個(gè)命名要使用的數據庫的方法。如果需要連接參數可在數據庫名前指定。例如,下列兩個(gè)命令使我們能連接到在本地主機和p i t - v i p e r.snake.net 上的samp_db 數據庫上:
除非另有指定,否則后面的例子都假定在激活mysql 時(shí),在命令行上給出samp_db 使其成為當前數據庫。如果激活數據庫時(shí)忘了在命令行上指定數據庫,只需發(fā)布USE samp_db 語(yǔ)句即可。
1.4.6 創(chuàng )建表
本節中,我們將創(chuàng )建樣例數據庫samp_db 所需的表。我們首先考慮美國歷史同盟需要的表。然后再考慮學(xué)分保存方案所需的表。在某些數據庫的書(shū)籍中,在這里要大講分析與設計、實(shí)體—關(guān)系圖、標準程序以及諸如此類(lèi)的東西。這里確實(shí)也可以講這些東西,但是我寧可只講點(diǎn)實(shí)用的東西,比方說(shuō),我們的數據庫應該是怎樣的:數據庫中將包含什么內容,每個(gè)表中有哪些數據以及由決定如何表示數據而帶來(lái)的一些問(wèn)題。這里所作出的關(guān)于數據表示的選擇并不是絕對的。在其他場(chǎng)合下,可能會(huì )選擇不同的方式來(lái)表示類(lèi)似的數據,這取決于應用的需要以及打算將數據派何用途。
1. 美國歷史同盟所需的表
美國歷史同盟的表設計相當簡(jiǎn)單:
■ 總統( p r e s i d e n t )表。此表含有描述每位總統的記錄。同盟站點(diǎn)上的聯(lián)機測驗要使用這個(gè)表。
■ 會(huì )員( m e m b e r )表。此表用來(lái)維護同盟每個(gè)會(huì )員的當前信息。這些信息將用來(lái)建立會(huì )員地址名錄的書(shū)面和聯(lián)機版本、發(fā)送會(huì )員資格更新提示等等。
(1) president表
president 表很簡(jiǎn)單,因此我們先討論它。這個(gè)表將包含每位美國總統的一些基本信息:
■ 姓名。姓名在一個(gè)表中可用幾種方式表示。如,可以用一個(gè)單一的列來(lái)存放完整的姓名,或者用分開(kāi)的列來(lái)分別容納名和姓。當然用單一的列更為簡(jiǎn)單,但是在使用上會(huì )帶來(lái)一些限制,如:
■ 如果先輸入只有名的姓名,則不可能對姓進(jìn)行排序。
■ 如果先輸入只有姓的姓名,就不可能對具有名的姓名進(jìn)行顯示。
■ 難以對姓名進(jìn)行搜索。例如,如果要搜索某個(gè)特定的姓,則必須使用一個(gè)特定的模式,并且查找與這個(gè)模式匹配的姓名。這樣較之只查找姓效率更低和更慢。member 表將使用單獨的名和姓的列以避免這些限制。名列還存放中名(注:西方國家的姓名一般將名放在前,姓放在后,而且除了有名和姓外,有時(shí)還有中名,這是在位置上介于名和姓之間的中間名字)或首字母。這樣應該不會(huì )削弱我們可能進(jìn)行的任何一種排序,因為一般不可能對中名進(jìn)行排序(或者甚至不會(huì )對名進(jìn)行排序)。姓名即可以“ Bush, George W. ”格式顯示,也可以“G e o rge W. B u s h”格式顯示。還有一種稍顯復雜一點(diǎn)的情形。一個(gè)總統( Jimmy Carter)在其姓名的末尾處有一
個(gè)“ J r. ”,這時(shí)怎樣做?根據名字打印的格式,這個(gè)總統的姓名顯示為“ J a m e s E . C a r t e r, J r.”或“C a r t e r, James E., Jr.”,“J r.”與名和姓都沒(méi)有關(guān)系,因此我們將建另外一個(gè)字段來(lái)存放姓名的后綴。這表明在試圖確定怎樣表示數據時(shí),即使一個(gè)特殊的值也可能會(huì )帶來(lái)問(wèn)題。它也表明,為什么在將數據放入數據庫前,盡量對數據值的類(lèi)型進(jìn)行了解是一個(gè)很好的想法。如果對數據了解不夠,那么有可能在已經(jīng)開(kāi)始使用一個(gè)表后,不得不更改該表的結構。這不一定是個(gè)災難,但通常應該避免。
■ 出生地(城市和州)。就像姓名一樣,出生地也可以用單個(gè)列或多個(gè)列來(lái)表示。使用單列更為簡(jiǎn)單些,但正如姓名中的情形一樣,獨立的多個(gè)列使我們可以完成用單個(gè)列不方便完成的事情。例如,如果城市和州分別給出,查找各位總統出生在哪個(gè)州的記錄就會(huì )更容易一些。
■ 出生日期和死亡日期。這里,唯一特殊的問(wèn)題是我們不能要求都填上死亡日期,因為有的總統現在還健在。MySQL 提供了一個(gè)特殊的值N U L L,表示“無(wú)值”,可將其用在死亡日期列中以表示“仍然健在”。
(2) member 表
存儲歷史同盟會(huì )員清單的member 表在每個(gè)記錄都包含單個(gè)人員的基本描述信息這一點(diǎn)上,類(lèi)似于president 表。但是每個(gè)member 的記錄所含的列更多,member 表的各列如下:
■ 姓名。使用如president 表一樣的三個(gè)列來(lái)表示:姓、名(如果可能的話(huà)還有中名)、后綴。
■ ID 號。這是開(kāi)始記錄會(huì )員時(shí)賦給每個(gè)會(huì )員的唯一值。以前同盟未用ID 號,但現在的記錄做得更有系統性,所以最好開(kāi)始使用ID 號。(我希望您找到有利于使用M y S Q L并考慮到其他的將它用于歷史同盟記錄的方法。使用數字,將member 表中的記錄與其他與會(huì )員有關(guān)的表中的記錄相關(guān)聯(lián)要更容易一些。)
■ 截止日期。會(huì )員必須定期更新他們的會(huì )員資格以免作廢。對于某些應用,可能會(huì )用到最近更新的日期,但是近更新日期不適合于歷史同盟。會(huì )員資格可在可變的年數內(一般為一年、二年、三年或五年)更新,而最近更新的日期將不能表示下一次更新必須在何時(shí)進(jìn)行。此外,歷史同盟還允許有終生會(huì )員。我們可以用未來(lái)一個(gè)很長(cháng)的日期來(lái)表示終生會(huì )員,但是用NULL 似乎更為合適,因為“無(wú)值”在邏輯上對應于“永不終止”。
■ 電子郵件地址。對于有電子郵件地址的會(huì )員,這將使他們能很容易地進(jìn)行相互之間的通信。作為歷史同盟秘書(shū),這使您能電子化地發(fā)送更新通知給會(huì )員,而用不著(zhù)發(fā)郵政信函。這比到郵局發(fā)送信函更容易,而且也不貴。還可以用電子郵件給會(huì )員發(fā)送他們的地址名錄條目的當前內容,并要求他們在有必要時(shí)更新信息。
■ 郵政地址。這是與沒(méi)有電子郵件(或沒(méi)有返回信息)的會(huì )員聯(lián)絡(luò )所需要的。將分別使用街道地址、城市、州和Zip 號。街道地址列又可以用于有諸如P.O. Box 123 而不是123 Elm St. 的會(huì )員的信箱號。我們假定所有同盟會(huì )員全都住在美國。當然,對于具有國際會(huì )員的機構,此假設過(guò)于簡(jiǎn)化了。如果希望處理多個(gè)國家的地址,還需要對不同國家的地址格式作一些工作。例如,這里的Zip 號就不是一個(gè)國際標準,有的國家有省而不是州。
■ 電話(huà)號碼。與地址字段一樣,這個(gè)列對于聯(lián)絡(luò )會(huì )員也是很有用的。
■ 特殊愛(ài)好的關(guān)鍵詞。假定每個(gè)會(huì )員一般都對美國歷史都有興趣,但可能有的會(huì )員對某些領(lǐng)域有特殊的興趣。此列記錄了這些特殊的興趣。會(huì )員可以利用這個(gè)信息來(lái)找到其他具有類(lèi)似興趣的會(huì )員。
(3) 創(chuàng )建表
現在我們已經(jīng)作好了創(chuàng )建歷史同盟表的準備。我們用C R E ATE TABLE 語(yǔ)句來(lái)完成這項工作,其一般格式如下:
其中tbl_name 代表希望賦予表的名稱(chēng)。column_specs 給出表中列的說(shuō)明,以及索引的說(shuō)明(如果有的話(huà))。索引能使查找更快;我們將在第4 章“查詢(xún)優(yōu)化”中對其作進(jìn)一步的介紹。
president 表的C R E ATE TABLE 語(yǔ)句如下所示:
如果想自己鍵入這條語(yǔ)句,則調用m y s q l,使samp_db 為當前數據庫:
然后,鍵入如上所示的C R E ATE TABLE 語(yǔ)句。(請記住,語(yǔ)句結尾要增加一個(gè)分號,否則mysql 將不知道哪兒是語(yǔ)句的結尾。)
為了利用來(lái)自樣例數據庫分發(fā)包的預先寫(xiě)下的描述文件來(lái)創(chuàng )建president 表,可從外殼程序運行下列命令:
不管用哪種方法調用m y s q l,都應該在命令行中數據庫名的前面指定連接參數(主機名、用戶(hù)名或口令)。C R E ATE TABLE 語(yǔ)句中每個(gè)列的說(shuō)明由列名、類(lèi)型(該列將存儲的值的種類(lèi))以及一些可能的列屬性組成。president 表中所用的兩種列類(lèi)型為VARCHAR 和D AT E。VA R C H A R(n)代表該列包含可變長(cháng)度的字符(串)值,其最大長(cháng)度為n 個(gè)字符??筛鶕谕址苡卸嚅L(cháng)來(lái)選擇n 值。
state 定義為VA R C H A R ( 2 );即所有州名都只用其兩個(gè)字符的縮寫(xiě)來(lái)表示。其他的字符串列則需要更長(cháng)一些,以便存放更長(cháng)的值。
我們使用過(guò)的其他列類(lèi)型為D AT E。這種列類(lèi)型表示該列存儲的是日期值,這一點(diǎn)也不令人吃驚。而令人吃驚的是,日期的表示以年份開(kāi)頭。其標準格式為“ Y Y Y Y- M M - D D”(例如,“1 9 9 9 - 0 7 - 1 8”)。這是日期表示的ANSI SQL 標準。我們用于president 表的唯一列屬性為N U L L(值可以缺少)和NOT NULL(必須填充值)。多數列是NOT NULL 的,因為我們總要有一個(gè)它們的值??捎蠳ULL 值的兩個(gè)列是s u ff i x(多數姓名沒(méi)有后綴)和d e a t h(有的總統仍然健在,所以沒(méi)有死亡日期)。member 表的C R E ATE TABLE 語(yǔ)句如下所示:
將此語(yǔ)句鍵入mysql 或執行下列外殼程序命令:
從列的類(lèi)型來(lái)看,member 表并不很有趣:所有列中,除了一列之外,其他列都是可變長(cháng)字符串。這個(gè)例外的列就是e x p i r a t i o n,為D ATE 型。終止日期值有一個(gè)缺省值為“0 0 0 0 - 0 0 -0 0”,這是一個(gè)非NULL 的值,它表示未輸入合法的日期值。這樣做的原因是expiration 可以是N U L L,它表示一個(gè)會(huì )員是終身會(huì )員。但是,因為此列可以為N U L L,除非另外指定一個(gè)不同的值,否則它將取缺省值“ 0 0 0 0 - 0 0 - 0 0”。如果創(chuàng )建了一個(gè)新會(huì )員記錄,但忘了指定終止日期,該會(huì )員將成為一個(gè)終身會(huì )員!通過(guò)采用缺省值“ 0 0 0 0 - 0 0 - 0 0”的方法,避免了這個(gè)問(wèn)題。它還向我們提供了一種手段,即可以定期地搜索這個(gè)值,以找出過(guò)去未正確輸入終止日期的記錄。
請注意,我們“忘了”放入會(huì )員ID 號的列。這是專(zhuān)門(mén)為了以后練習使用A LTER TA B L E語(yǔ)句而遺留下的?,F在讓我們來(lái)驗證一下MySQL 是否確實(shí)如我們所期望的那樣創(chuàng )建了表。在mysql 中,發(fā)布下列查詢(xún):
與MySQL 3.23 一樣,此輸出還包括了顯示訪(fǎng)問(wèn)權限信息的另一個(gè)列,這里沒(méi)有給出,
因為它使每行太長(cháng),不易顯示。
這個(gè)輸出結果看上去和我們所期望的非常一致,除了state 列的信息顯示它的類(lèi)型為C H A R ( 2 )。這就有點(diǎn)古怪了,我們不是定義它為VARCHAR(2) 了嗎?是的,是這樣定義的,但是MySQL 已經(jīng)悄悄地將此類(lèi)型從VARCHAR 換成了C H A R。原因是為了使短字符串列的
存儲空間利用更為有效,這里不多討論。如果希望詳細了解,可參閱第3 章中關(guān)于A(yíng) LT E RTABLE 語(yǔ)句的介紹。但對這里的使用來(lái)說(shuō),兩種類(lèi)型沒(méi)有什么差別。
如果發(fā)布一個(gè)DESCRIBE member 查詢(xún),mysql 也會(huì )顯示member 表的類(lèi)似信息。DESCRIBE 在您忘了表中的列名、需要知道列的類(lèi)型、了解列有多寬等的時(shí)候很有用。它對于了解MySQL 存儲表行中列的次序也很有用。列的這個(gè)存儲次序在使用I N S E RT 或LOAD DATA 語(yǔ)句時(shí)非常重要,因為這些語(yǔ)句期望列值以缺省列的次序列出。DESCRIBE 可以省寫(xiě)為D E S C,或者,如果您喜歡鍵入較多字符,則D E S C R I B Etbl_name 另一個(gè)等同的語(yǔ)句為SHOW COLUMNS FROM tbl_name。
如果忘了表名怎么辦?這時(shí)可以使用SHOW TA B L E S。對于samp_db 數據庫,我們目前
為止創(chuàng )建了兩個(gè)表,其輸出結果如下:
如果您甚至連數據庫名都記不住,可在命令行上調用mysql 而不用給出數據庫名,然后發(fā)布SHOW DATABASES 查詢(xún):
數據庫的列表在不同的服務(wù)器上是不同的,但是至少可以看到samp_db 和m y s q l;后一個(gè)數據庫存放控制MySQL 訪(fǎng)問(wèn)權限的授權表。DESCRIBE 與SHOW 查詢(xún)具有可從外殼程序中使用的命令行等同物,如下:
% mysqlshow 與SHOW DATABASES 一樣列出所有數據庫
% mysqlshow d b _ n a m e 與SHOW TABLES 一樣列出給定數據庫的表
% mysqlshow db_name tbl_name 與DESCRIBE tbl_name 一樣,列出給定表中的列
2. 用于學(xué)分保存方案的表
為了知道學(xué)分保存方案需要什么表,我們來(lái)看看在原來(lái)學(xué)分簿上是怎樣記學(xué)分的。圖1 - 2示出學(xué)分簿的一頁(yè)。該頁(yè)的主體是一個(gè)記錄學(xué)分矩陣。還有一些對學(xué)分有意義的必要信息。學(xué)生名和ID 號列在矩陣的一端。(為了簡(jiǎn)單好看,只列出了四個(gè)學(xué)生。)在矩陣頂端,記錄了進(jìn)行測驗和測試的日期。圖中示出9月3號、6號、1 6號和2 3號進(jìn)行測驗, 9月9號和1 0月1號進(jìn)
行測試。
為了利用數據庫來(lái)記錄這些信息,需要一個(gè)學(xué)分表。這個(gè)表中應該包含什么記錄呢?很明顯,每一行都需要有學(xué)生名、測驗或測試的日期以及學(xué)分。圖1-3 示出了用這樣的表表示的一些來(lái)自學(xué)分簿的學(xué)分。(日期以MySQL 的表示格式“Y Y Y Y- M M - D D”表示。)
但是,以這種方式設置表似乎有點(diǎn)問(wèn)題。好像少了點(diǎn)什么。請看圖1 - 3中的記錄,我們分辨不出是測驗的學(xué)分還是測試的學(xué)分。如果測驗和測試的學(xué)分權重不同,在確定最終的學(xué)分等級時(shí)知道學(xué)分的類(lèi)型是很重要的?;蛟S可以試著(zhù)從學(xué)分的取值范圍來(lái)確定學(xué)分的類(lèi)型(測驗的學(xué)分一般比測試的學(xué)分少),但是這樣做很不方便,因為這需要進(jìn)行判斷,而且在數據中也不明顯??梢酝ㄟ^(guò)記錄學(xué)分的類(lèi)型來(lái)進(jìn)行區分,如對學(xué)分表增加一列,此列包含“ T”或“Q”以表示是“測試”或是“測驗”,如圖1-4 所示。這具有使學(xué)分數據類(lèi)型清析易辨的優(yōu)點(diǎn)。不利的地方是這個(gè)信息有點(diǎn)冗余。顯然對具有同一給定日期的記錄,學(xué)分的類(lèi)型列總是取相同的值。9月2 3日的學(xué)分總是為“ Q”類(lèi)型,而1 0月1日的學(xué)分其類(lèi)型總是具有“ T”類(lèi)型。這樣令人很不滿(mǎn)意。如果我們以這種方式記錄一組測驗或測試的學(xué)分,不僅要為每個(gè)新記錄輸入相同的日期,而且還要一再重復地輸入相同的學(xué)分類(lèi)型。誰(shuí)會(huì )希望一再輸入冗余的信息呢?
我們可以試試另外一種表示。不在score 表中記錄學(xué)分類(lèi)型,而是從日期上區分它們。我們可以做一個(gè)日期列表,用它來(lái)記錄每個(gè)日期發(fā)生的“學(xué)分事件”(測驗或測試)。然后可以將學(xué)分與這個(gè)事件列表中的信息結合,確定學(xué)分是測驗學(xué)分還是測試學(xué)分。這只要將score 表記錄中的日期與event 表中的日期相匹配得出事件類(lèi)型即可。圖1 - 5示出這個(gè)表的設計并演示了score 表記錄與9月2 3日這個(gè)日期相關(guān)聯(lián)的工作。通過(guò)將score 表中的記錄與event 表中記錄相對應,我們知道這個(gè)學(xué)分來(lái)自測驗。
這比根據某些猜測來(lái)推斷學(xué)分類(lèi)型要好得多;我們可以根據明確記錄在數據庫中的數據來(lái)直接得到學(xué)分類(lèi)型。這也比在score 表中記錄學(xué)分類(lèi)型更好,因為我們只需對每個(gè)類(lèi)型記錄一次。
但是,在第一次聽(tīng)到這種事情時(shí)(即結合使用多個(gè)表中的信息),可能會(huì )想,“嗯,這是一個(gè)好主意,但是不是要做很多工作呢?會(huì )不會(huì )使工作更復雜了?”在某種程度上,這種想法是對的。處理兩個(gè)記錄表比處理一個(gè)要復雜。但是再來(lái)考察一下學(xué)分簿(見(jiàn)圖1 - 2)。不是也記錄了兩套東西嗎?考慮下列事實(shí):
■ 在學(xué)分矩陣中用兩個(gè)單元記錄學(xué)分,其中每個(gè)單元都是按學(xué)生名字和日期(在矩陣的旁邊和頂上)進(jìn)行索引的。這代表了一組記錄;與score 表的作用相同。
■ 怎樣知道每個(gè)日期代表的事件類(lèi)型呢?在日期上方寫(xiě)了字符“ T”或“Q”!因此,也在矩陣頂上記錄了日期和學(xué)分類(lèi)型之間的關(guān)系。它代表第二組記錄;與event 表的作用相同。
換句話(huà)說(shuō),這里建議在兩個(gè)表中記錄信息與用學(xué)分簿記錄信息所做的工作沒(méi)什么不同。唯一不同的是,這兩組信息在學(xué)分簿中不是那么明顯地被分開(kāi)。在圖1 - 5中所示的event 表的設計中加了一個(gè)要求,那就是日期必須是唯一的,因為要用它連接score 與event 表的記錄。換句話(huà)說(shuō),同一天不能進(jìn)行兩次測驗,或者同一天不能進(jìn)行一次測驗和一次測試。否則,將會(huì )在score 表中有兩個(gè)記錄并且在event 表中也有兩個(gè)記錄,全都具有相同的日期,這時(shí)就不知道應如何將score 的記錄與event 的記錄進(jìn)行匹配。如果每天不多于一個(gè)學(xué)分事件,這就是一個(gè)永遠不會(huì )出現的問(wèn)題,可是事實(shí)并非如此簡(jiǎn)單。有時(shí),一天中可能會(huì )有不止一個(gè)學(xué)分事件。我常聽(tīng)有的人說(shuō)他們的數據,“那種古怪情況從不會(huì )出現。”然而,如果這種情況確實(shí)出現時(shí),就必須重新設計表以適應這種情況引起的問(wèn)題。最好是預先考慮以后可能出現的問(wèn)題,并預先準備好怎樣處理他們。因此,我們假定有時(shí)可能會(huì )需要同一天記錄兩組學(xué)分。我們怎樣處理呢?如果出現這種情況,問(wèn)題并不難解決。只要對處理數據的方式作一點(diǎn)小的更改,就可使同一日期上有多個(gè)事件而不會(huì )引起問(wèn)題:
1) 增加一個(gè)列到event 表,并用它來(lái)給表中每個(gè)記錄分配一個(gè)唯一的編號。實(shí)際上這就給了每個(gè)事件一個(gè)唯一的ID 號,因此我們稱(chēng)該列為event_id 列。(如果覺(jué)得這好像是做傻事,可看一下圖1-2 中的學(xué)分簿,其中已經(jīng)有這個(gè)特征了。事件ID 正好與學(xué)分簿分數矩陣中列號相似。這個(gè)編號可能沒(méi)有清晰地寫(xiě)在那兒并標上“事件I D,”但是它確實(shí)在那兒。)
2) 當向score 表中輸入學(xué)分時(shí),輸入的是事件ID 而不是日期。這些改變的結果如圖1-6 所示?,F在連接score 和event 表時(shí),用的是事件ID 而不是日期,而且不僅用event 表來(lái)決定每個(gè)學(xué)分的類(lèi)型,而且還用它來(lái)決定其日期。并且在event 表中不再有日期必須唯一這個(gè)限制,而唯一的是事件I D。這表示同一天可以有一打測試和測驗,而且能夠在記錄里邊直接保存它們。(毫無(wú)疑問(wèn),學(xué)生們聽(tīng)到這個(gè)一定渾身發(fā)抖。)不幸的是,從人的觀(guān)點(diǎn)來(lái)看,圖1-6 中的表設計較前一個(gè)更不能令人滿(mǎn)意。score 表也更為抽象一些,因為它包含的從直觀(guān)上可以理解的列更少。而圖1-4 中此表的設計直觀(guān)且容易理解,因為那個(gè)score 表具有日期和學(xué)分類(lèi)型的列。當前的score 表如圖1-6 所示,日期和學(xué)分類(lèi)型的列都沒(méi)有了。這極大地去除了作為人能夠很容易考慮的一切。誰(shuí)希望看到其中有“事件I D”的score 表?如果有的話(huà),也不代表我們大多數人。
此時(shí),可看到能夠電子化地完成學(xué)分記錄,且在賦予學(xué)分等級時(shí)不必做各種乏味的手工計算。但是,在考慮了如何實(shí)際在一個(gè)數據庫中表示學(xué)分信息后,又會(huì )被怎樣抽象和拆分組成學(xué)分信息的表示難住了。自然會(huì )產(chǎn)生一個(gè)問(wèn)題:“根本不使用數據庫可能會(huì )更好一些?或許MySQL 不適合我?”正如您所猜測的那樣,筆者將從否定的方面對這個(gè)問(wèn)題進(jìn)行回答,否則這本書(shū)就沒(méi)必要再往下寫(xiě)了。不過(guò),在考慮如何做一件工作時(shí),應考慮各種情況并提問(wèn)是否最好不使用數據庫系統(如M y S Q L)而使用一些別的東西(如電子表格等):
■ 學(xué)分簿有行和列,而電子表格也有。這使學(xué)分簿和電子表格在概念上和外觀(guān)上都非常類(lèi)似。
■ 電子表格能夠完成計算,可以利用一個(gè)計算字段來(lái)累計每個(gè)學(xué)生的學(xué)分。但是,要對測驗和測試進(jìn)行加權可能有點(diǎn)麻煩,但這也是可以辦得到的。另一方面,如果希望只查看某部分數據(如只查看學(xué)分或測試),進(jìn)行諸如男孩與女孩的比較,或以一種靈活的方式顯示合計信息等,情況又大有不同了。電子表格的功能顯得要差一些,而關(guān)系數據庫系統完成這些工作相當容易。另外要考慮的一點(diǎn)是為了在關(guān)系數據庫中進(jìn)行表示而對數據進(jìn)行抽象和分解,這個(gè)問(wèn)題并不真的那么難以應付。只要考慮安排數據庫使其不會(huì )以一種對您希望做的事無(wú)意義的方式來(lái)表示數據即可。但是,在確定了表示方式之后,就要靠數據庫引擎來(lái)協(xié)調和表示數據了。您肯定不會(huì )希望將它視為一堆支離破碎的東西。
例如,在從score 表中檢索學(xué)分時(shí),不希望看到事件I D;但希望看到日期。這沒(méi)有什么問(wèn)題。數據庫將會(huì )根據事件ID 從event 表中查找出日期。您還可能想要看看是測驗的學(xué)分或測試的學(xué)分。這也不成問(wèn)題。數據庫將用相同的方法查找出學(xué)分類(lèi)型,也是利用事件I D。請記住,這就是如像MySQL 這樣的關(guān)系數據庫的優(yōu)勢所在,即,使一樣東西與另一樣東西相關(guān)聯(lián),以便從多個(gè)來(lái)源得出信息并以您實(shí)際想看到的形式提供出來(lái)。在學(xué)分保存數據的情況中,MySQL 確實(shí)利用事件ID 將信息組合到了一起,而無(wú)需人工來(lái)完成這件事。
現在我們先來(lái)看看,如何使MySQL 完成這種將一個(gè)東西與另一個(gè)東西相聯(lián)系的工作。
假定希望看到1 9 9 9年9月2 3號的學(xué)分,針對某個(gè)特定日期中給出的事件的學(xué)分查詢(xún)如下所示:
相當嚇人,是嗎?這個(gè)查詢(xún)通過(guò)將score 表的記錄與event 表的記錄連接(關(guān)聯(lián))來(lái)檢索學(xué)生名、日期、學(xué)分和學(xué)分的類(lèi)型。其結果如下所示:
您肯定注意到了,它與圖1-4 中給出的表設計相同,而且不需要知道事件ID 就可得出這個(gè)結果,只需指出感興趣的日期并讓MySQL 查找出哪個(gè)學(xué)分記錄具有該日期即可。如果您一直擔心抽象和分解會(huì )使我們損失一些東西的話(huà),看到這個(gè)世界,就不會(huì )有這種擔心了。
當然,在考慮過(guò)查詢(xún)后,您還可能對其他別的東西產(chǎn)生擔心。即,這個(gè)查詢(xún)看上去有點(diǎn)長(cháng)并且也有點(diǎn)復雜;是不是做了很多工作寫(xiě)出這樣的東西只是為了查找某個(gè)給定日期的學(xué)分?是的,確實(shí)是這樣。但是,在每次想要發(fā)布一個(gè)查詢(xún)時(shí),有幾種方法可以避免鍵入多行的S Q L。一般情況下,一旦您決定如何執行這樣一個(gè)查詢(xún)并將它保存起來(lái)后,就可以按需要多次執行它。我們將在1 . 5節“與mysql 交互的技巧”中介紹怎樣完成這項工作。
在上述查詢(xún)的介紹中,我們有點(diǎn)超前了。不過(guò),這個(gè)查詢(xún)比起我們要實(shí)際用來(lái)得出學(xué)分的查詢(xún)是有點(diǎn)簡(jiǎn)單了。原因是,我們還要對表的設計作更多的修改。我們將采用一個(gè)唯一的學(xué)生I D,而不在score 表中記錄學(xué)生名。(即,我們將使用來(lái)自學(xué)分簿的“ I D”列的值而不是來(lái)自“ N a m e”列的值。)然后,創(chuàng )建另一個(gè)稱(chēng)為student 的表來(lái)存放name 和student_id 列(見(jiàn)圖1 - 7)。
為什么要作出這種修改呢?只有一個(gè)原因,可能有兩個(gè)學(xué)生有相同的名字。采用唯一的學(xué)生ID 號可幫助區分他們的學(xué)分。(這與利用唯一的事件ID 而不是日期來(lái)分辨出相同日期的測試或測驗完全類(lèi)似。)在對表的設計作了這樣的修改后,實(shí)際用來(lái)獲得給定日期的學(xué)分查詢(xún)變得更為復雜了一些,這個(gè)查詢(xún)如下:
如果您不能立即清楚地讀懂這個(gè)查詢(xún)的意思的話(huà),也不必擔心。在進(jìn)一步深入這個(gè)教程之后,就能看懂這個(gè)查詢(xún)了。將會(huì )從圖1 - 7中注意到,在student 表中增加了點(diǎn)學(xué)分簿中沒(méi)有的東西。它包含了一個(gè)性別列。這便可以做一些簡(jiǎn)單的事情,如對班級中男孩和女孩的人數計數;也可以做一些更為復雜的事情,如比較男孩和女孩的學(xué)分。我們已經(jīng)設計完了學(xué)分保存的幾乎所有的表?,F在只需要另外
一個(gè)表來(lái)記錄出勤情況即可。這個(gè)表的內容相對較為直觀(guān),即,一個(gè)學(xué)生ID 號和一個(gè)日期(見(jiàn)圖1 - 8)。表中的每行表示特定的學(xué)生在
給定的日期缺勤。在學(xué)分時(shí)段末,我們將調用MySQL 的計數功能來(lái)匯總此表的內容,以便得出每個(gè)學(xué)生的缺勤數。
既然現在已經(jīng)知道學(xué)分保存的各個(gè)表的結構,現在可以創(chuàng )建它們了。student 表的C R E ATE TABLE 語(yǔ)句如下:
將上述語(yǔ)句鍵入mysql 或執行下列外殼程序命令:
C R E ATE TABLE 語(yǔ)句創(chuàng )建了一個(gè)名為student 的表,它含有三列,分別為: n a m e、s e x和s t u d e n t _ i d。name 是一個(gè)可變長(cháng)的字符串列,最多可存放20 個(gè)字符。這個(gè)名字的表示比歷史同盟表中所用的表示要簡(jiǎn)單,它只用了單一的列而不是分別的名和姓列。這是因為我們已經(jīng)預先知道,不存在無(wú)需做另外的工作就使得在多個(gè)列上工作得更好的查詢(xún)樣例。sex 表示學(xué)生是男孩還是女孩。這是一個(gè)E N U M(枚舉)列,表示只能取明確地列在說(shuō)明中的值之一,這里列出的值為:“F”和“M”,分別表示女和男。在某列只具有一組有限值時(shí),ENUM 類(lèi)型非常有用。我們可以用CHAR(1) 來(lái)代替它,但是ENUM 更明確規定了列可以取什么值。如果對包括一個(gè)ENUM 列的表發(fā)布一條DESCRIBE tbl_name 語(yǔ)句,MySQL 將確切地顯示可取的值有哪些。順便說(shuō)一下, ENUM 列中的值不一定只是單個(gè)字符。此列還可以定義為E N U M(‘f e m a l e’,‘m a l e’)。
student_id 為一個(gè)整數型列,它將包含唯一的ID 號。通常,大概會(huì )從一個(gè)中心資料來(lái)源處(如學(xué)校辦公室)取得學(xué)生的ID 號,但在這里是我們自己定的。雖然student_id 列只包含一個(gè)數,但其定義包括幾個(gè)部分:
■ INT 說(shuō)明此列的值必須取整數(即無(wú)小數部分)。
■ UNSIGNED 不允許負數。
■ NOT NULL 表示此列的值必須填入。(任何學(xué)生都必須有一個(gè)ID 號。)
■ A U TO_INCREMENT 是MySQL 中的一個(gè)特殊的屬性。其作用為:如果在創(chuàng )建一個(gè)新的student 表記錄時(shí)遺漏了student_id 的值(或為N U L L),MySQL 自動(dòng)地生成一個(gè)大于當前此列中最大值的唯一ID 號。在錄入學(xué)生表時(shí)將用到這個(gè)這特性,錄入學(xué)生表時(shí)可以只給出name 和sex 的值,讓MySQL 自動(dòng)生成student_id 列值。
■ P R I M A RY KEY 表示相應列的值為快速查找進(jìn)行索引,并且列中的每個(gè)值都必須是惟一的。這樣可防止同一名字的I D出現兩次,這對于學(xué)生ID 號來(lái)說(shuō)是一個(gè)必須的特性。(不僅如此,而且MySQL 還要求每個(gè)A U TO_INCREMENT 列都具有一個(gè)惟一索引。)如果您不理解A U TO_INCREMENT 和P R I M A RY KEY 的含義,只要將其想像為一種為每個(gè)學(xué)生產(chǎn)生ID 號的魔術(shù)方法即可。除了要求值唯一外,沒(méi)有什么別的東西。請注意:如果確實(shí)打算從學(xué)校辦公室取得學(xué)生ID 號而不是自動(dòng)生成它們,則可以按相同的方法定義student_id 列,只不過(guò)不定義A U TO_INCREMENT 屬性即可。event 表如下定義:
將此語(yǔ)句鍵入mysql 或執行下列外殼程序的命令:
所有列都定義為NOT NULL,因為它們中任何一個(gè)值都不能省略。date 列存儲標準的MySQL DATE 日期值,格式為“Y Y Y Y- M M - D D”(首先是年)。type 代表學(xué)分類(lèi)型。像student 表中的sex 一樣,type 也是一個(gè)枚舉列。所允許的值為“T”和“Q”,分別表示“測試”和“測驗”。event_id 是一個(gè)AUTO_INCREMENT 列,類(lèi)似于student 表中的student_id 列。采用AUTO_INCREMENT 允許生成唯一的事件ID 值。正如student 表中的student_id 列一樣,與值的惟一性相比,某個(gè)特定的值并不重要。score 表如下定義:
將此語(yǔ)句鍵入mysql 或執行下列外殼程序的命令:
score 為一個(gè)INT (整型)列。即,假定學(xué)分值總是為一個(gè)整數。如果希望使學(xué)分值具有小數部分,如5 8 . 5,應該采用浮點(diǎn)列類(lèi)型,如F L O AT 或D E C I M A L。student_id 列和event_id 列都是整型,分別表示每個(gè)學(xué)分所對應的學(xué)生和事件。通過(guò)利用它們來(lái)連接到student 和event 表,我們能夠知道學(xué)生名和事件的日期。我們將兩個(gè)列組成了P R I M A RY KEY。這保證我們不會(huì )對同一測驗或測試重復一個(gè)學(xué)生的學(xué)分。而且,這樣還很容易在以后更改某個(gè)學(xué)分。例如,在發(fā)現學(xué)分錄入錯時(shí),可以在利用MySQL 的R E P L A C E語(yǔ)句放入一個(gè)新記錄,替換掉舊的記錄。不需要執行DELETE 語(yǔ)句與I N S E RT 語(yǔ)句;M y S Q L自動(dòng)替我們做了。請注意,它是惟一的event_id 和student_id 的組合。在score 表中,兩者自身都可能不惟一。一個(gè)event_id 值可有多個(gè)學(xué)分記錄(每個(gè)學(xué)生對應一個(gè)記錄),而每個(gè)student_id 值都對應多個(gè)記錄(每個(gè)測驗和測試有一個(gè)記錄)。用于出勤情況的absence 表如下定義:
將此語(yǔ)句鍵入mysql 或執行下列外殼程序的命令:
student_id 和date 列兩者都定義為NOT NULL,不允許省略值。應定義這兩列的組合為主鍵,以免不當心建立了重復的記錄。重要的是不要對同一天某個(gè)學(xué)生的缺曠進(jìn)行重復計數。
1.4.7 增加新記錄
至此,我們的數據庫及其表都已經(jīng)創(chuàng )建了,在下一節“檢索信息”中,我們將看到怎樣從數據庫中取出數據?,F在我們先將一些數據放入表中。在數據庫中加入數據有幾種方法??赏ㄟ^(guò)發(fā)布I N S E RT 語(yǔ)句手工將記錄插入某個(gè)表中。還可以通過(guò)從某個(gè)文件讀取它們來(lái)增加記錄,在這個(gè)文件中,記錄既可以是利用L O A DD ATA 語(yǔ)句或mysqlimport 實(shí)用程序裝入的原始數據值,也可以是預先寫(xiě)成可饋入mysql 的I N S E RT 語(yǔ)句的形式。本節介紹將記錄插入表的每種方法。您所應做的是演習各種方法以明了它們是如何起作用的。然后到本節結束處運行那兒給出的命令來(lái)清除表并重裝它們。這樣做,能夠保證表中含有作者撰寫(xiě)下一節時(shí)所處理的相同記錄,您也能得到相同的結果。讓我們開(kāi)始利用I N S E RT 語(yǔ)句來(lái)增加記錄,這是一個(gè)SQL 語(yǔ)句,需要為它指定希望插入數據行的表或將值按行放入的表。I N S E RT 語(yǔ)句具有幾種形式:
■ 可指定所有列的值
例如:
“I N TO”一詞自MySQL 3.22.5 以來(lái)是可選的。(這一點(diǎn)對其他形式的I N S E RT 語(yǔ)句也成立。)VALUES 表必須包含表中每列的值,并且按表中列的存放次序給出。(一般,這就是創(chuàng )建表時(shí)列的定義次序。如果不能肯定的話(huà),可使用DESCRIBE tbl_name 來(lái)查看這個(gè)次序。)在MySQL 中,可用單引號或雙引號將串和日期值括起來(lái)。上面例子中的N U L L值是用于student 和event 表中的A U TO_INCREMENT 列的。(插入“錯誤”的值將導致下一個(gè)student_id 或event_id 號的自動(dòng)生成。)自3.22.5 以來(lái)的MySQL 版本允許通過(guò)指定多個(gè)值的列表,利用單個(gè)的I N S E RT語(yǔ)句將幾行插入一個(gè)表中,如下所示:
例如:
這比多個(gè)I N S E RT 語(yǔ)句的鍵入工作要少,而且服務(wù)器執行的效率也更高。
■ 可以給出要賦值的那個(gè)列,然后再列出值。這對于希望建立只有幾個(gè)列需要初始設置的記錄是很有用的。
例如:
自MySQL 3.22.5 以來(lái),這種形式的I N S E RT 也允許多個(gè)值表:
在列的列表中未給出名稱(chēng)的列都將賦予缺省值。
■ 自MySQL 3.22 .10 以來(lái),可以col_name = value 的形式給出列和值。
例如:
在SET 子句中未命名的行都賦予一個(gè)缺省值。使用這種形式的I N S E RT 語(yǔ)句不能插入多行。將記錄裝到表中的另一種方法是直接從文件讀取數據值??梢杂肔OAD DATA 語(yǔ)句或用mysqlimport 實(shí)用程序來(lái)裝入記錄。LOAD DATA 語(yǔ)句起批量裝載程序的作用,它從一個(gè)文件中讀取數據??稍趍ysql 內使用它,如下所示:
該語(yǔ)句讀取位于客戶(hù)機上當前目錄中數據文件m e m b e r.txt 的內容,并將其發(fā)送到服務(wù)器裝入member 表。如果您的MySQL 版本低于3 . 2 2 . 1 5,則LOAD DATA LOCAL 不起作用,因為那時(shí)從客戶(hù)機讀取數據的能力是在LOAD DATA 上的。(沒(méi)有LOCAL 關(guān)鍵字,被讀取的文件必須位于服務(wù)器主機上,并且需要大多數MySQL 用戶(hù)都不具備的服務(wù)器訪(fǎng)問(wèn)權限。)缺省時(shí),LOAD DATA 語(yǔ)句假定列值由tab 鍵分隔,而行則以換行符結束。還假定各個(gè)值是按列在表中的存放次序給出的。也有可能需要讀取其他格式的文件,或者指定不同的列次
序。更詳細的內容請參閱附錄D的LOAD DATA 的條款。mysqlimport 實(shí)用程序起LOAD DATA 的命令行接口的作用。從外殼程序調用mysqlimport ,它生成一個(gè)LOAD DATA 語(yǔ)句:
mysqlimport 生成一個(gè)LOAD DATA 語(yǔ)句,此語(yǔ)句使m e m b e r.txt 文件被裝入member 表。如果您的MySQL 版本低于3 . 2 2 . 1 5,這個(gè)實(shí)用程序不起作用,因為--local 選項需要L O A DD ATA LOCAL。正如使用mysql 一樣,如果您需要指定連接參數,可在命令行上數據庫名前指定它們。mysqlimport 從數據文件名中導出表名(它將文件名第一個(gè)圓點(diǎn)前的所有字符作為表名)。例如,m e m b e r.txt 將被裝入member 表,而president.txt 將被裝入president 表。如果您有多個(gè)需要裝入單個(gè)表的文件,應仔細地選擇文件名,否則mysqlimport 將不能使用正確的表名。對于如像member1.txt 與member2.txt 這樣的文件名, mysqlimport 將會(huì )認為相應的表名為
member1 和m e m b e r 2。不過(guò),可以使用如m e m b e r.1.txt 和m e m b e r.2.txt 或m e m b e r.txt1 和m e m b e r.txt2 這樣的文件名。在試用過(guò)這些記錄追加的方法后,應該清除各個(gè)表并重新裝載它們,以便它們的內容與下一節假定的內容相同。從外殼程序執行下列命令:
每個(gè)文件都含有一個(gè)刪除可能曾經(jīng)插入到表中的記錄的DELETE 語(yǔ)句,后跟一組INSERT 語(yǔ)句以初始化表的內容。如果不希望分別鍵入這些命令,可試一下下列語(yǔ)句:
1.4.8 檢索信息
現在各個(gè)表已經(jīng)創(chuàng )建并裝有數據了,因此讓我們來(lái)看看可以對這些數據做點(diǎn)什么。SELECT 語(yǔ)句允許以一般的或特殊的方式檢索和顯示表中的信息。它可以顯示表的整個(gè)內容:
或者只顯示單個(gè)行中單個(gè)列的內容:
SELECT 語(yǔ)句有幾個(gè)子句(部件),可以根據需要用來(lái)檢索感興趣的信息。每個(gè)子句都可簡(jiǎn)單、可復雜,從而SELECT 作為一個(gè)總的語(yǔ)句也繁簡(jiǎn)皆宜。但是,可以放心,本書(shū)中不會(huì )有花一個(gè)鐘頭來(lái)編寫(xiě)的長(cháng)達數頁(yè)的查詢(xún)。(我在書(shū)中看到有很長(cháng)的查詢(xún)時(shí),一般會(huì )立即跳過(guò)它們,因此我猜您也會(huì )這樣。)SELECT 語(yǔ)句的一般形式為:SELECT 要選擇的東西FROM 一個(gè)或多個(gè)表WHERE 數據必須滿(mǎn)足的條件記住,SQL 為一個(gè)自由格式的語(yǔ)言,因此在您編寫(xiě)SELECT 查詢(xún)時(shí),語(yǔ)句的斷行不必嚴格依照本書(shū)。
為了編寫(xiě)SELECT 語(yǔ)句,只需指定需要檢索什么,然后再選擇某些子句即可。剛才給出的子句“ F R O M”、“W H E R E”是最常用的,還有一些其他的子句,如GROUP BY、O R D E RBY 和LIMIT 等。FROM 子句一般都要給出,但是如果不從表中選擇數據,也可不給出。例如,下列查詢(xún)只顯示某些可以直接計算而不必引用任何表的表達式的值,因此不需要用FROM 子句:
在確實(shí)使用一個(gè)FROM 子句指定了要從其中檢索數據的表時(shí), SELECT 語(yǔ)句的最“普通”的格式是檢索所有內容。用“ *”來(lái)表示“所有列”。下面的查詢(xún)將從student 表中檢索所有行并顯示:
各列按它們MySQL 在表中存放的次序出現。該次序與發(fā)布DESCRIBE student 語(yǔ)句時(shí)顯示的列次序相同。(例子末尾的“. . .”表示此查詢(xún)返回的輸出行比這里顯示的還要多。)可明確地命名希望得到的一列或多列。如果只選擇學(xué)生名,發(fā)布下列語(yǔ)句:
如果名字不止一列,可用逗號分隔它們。下列的語(yǔ)句與SELECT * FROM student 等價(jià),只是明確地指出了每一列:
可按任意次序給出列:
如果有必要,同一列甚至也可以給出多次,雖然這樣做一般是沒(méi)有意義的。列名在MySQL 中不區分大小寫(xiě)的。下面的查詢(xún)是等同的:
數據庫和表名有可能區分大小寫(xiě)的;這有取決服務(wù)器主機上使用的文件系統。在U N I X上運行的服務(wù)器對數據庫名和表名是區分大小寫(xiě)的,因為UNIX 的文件名是區分大小寫(xiě)的。Windows 的文件名不區分大小寫(xiě),因此運行在Windows 上的服務(wù)器對數據庫名和表名不區分
大小寫(xiě)。MySQL 允許您一次從多個(gè)表中選擇列。我們將這個(gè)內容留到“從多個(gè)表中檢索信息”小節去介紹。
1. 指定檢索條件
為了限制SELECT 語(yǔ)句檢索出來(lái)的記錄集,可使用WHERE 子句,它給出選擇行的條件??赏ㄟ^(guò)查找滿(mǎn)足各種條件的列值來(lái)選擇行。
可查找數字值:
也可以查找串值。(注意,一般串的比較是不區分大小寫(xiě)的。)
可以查找日期值:
可搜索組合值:
WHERE 子句中的表達式可使用表1-1 中的算術(shù)運算符、表1-2 的比較運算符和表1-3 的邏輯運算符。還可以使用圓括號將一個(gè)表達式分成幾個(gè)部分??墒褂贸A?、表列和函數來(lái)完成運算。在本教程的查詢(xún)中,我們有時(shí)使用幾個(gè)MySQL 函數,但是MySQL 的函數遠不止這里
給出的這些。請參閱附錄C,那里給出了所有MySQL 函數的清單。
在用表達式表示一個(gè)需要邏輯運算的查詢(xún)時(shí),要注意別混淆邏輯與運算符與我們平常使用的“與”的含義。假如希望查找“出生在Vi rginia 的總統與出生在Maryland 的總統”。應該注意怎樣表示“與”的關(guān)系,能寫(xiě)成如下的查詢(xún)嗎?
錯了,因為這個(gè)查詢(xún)的意思是“選擇既出生在Vi rginia 又出生在M a r y l a n d的總統”,不可能有同時(shí)出生在兩個(gè)地點(diǎn)的總統,因此這個(gè)查詢(xún)無(wú)意義。在英語(yǔ)中,可以用“a n d”表示這種選擇,但在SQL 中,應該用OR 來(lái)連接兩個(gè)條件,如下所示:
這有時(shí)是可以覺(jué)察到的,不僅僅是在編寫(xiě)自己的查詢(xún)時(shí)可以覺(jué)察到,而且在為他人編寫(xiě)查詢(xún)時(shí)也可以知道。最好是在他人描述想要檢索什么時(shí)仔細聽(tīng),但不一定使用相同的邏輯運算符將他人的描述轉錄成SQL 語(yǔ)句。對剛才所舉的例子,正確的英語(yǔ)等價(jià)描述為“選擇出生在Vi rginia 或者出生在Maryland 的總統。”
2. NULL 值
NULL 值是特殊的;因為它代表“無(wú)值”。不可能以評估兩個(gè)已知值的相同方式來(lái)將它與已知值進(jìn)行評估。如果試圖與通常的算術(shù)比較運算符一道使用N U L L,其結果是未定義的:
為了進(jìn)行NULL 值的搜索,必須采用特殊的語(yǔ)法。不能用= 或!= 來(lái)測試等于NULL 或不等于N U L L,取而代之的是使用IS NULL 或IS NOT NULL 來(lái)測試。例如,因為我們將健在總統的死亡日期表示為N U L L,那么可按如下語(yǔ)句查找健在的總統:
MySQL3.23 及以后的版本具有一個(gè)特殊的MySQL 專(zhuān)有的比較運算符“ < = >”,即使是NULL 與NULL 的比較,它也是可行的。用這個(gè)比較運算符,可將前面的兩個(gè)查詢(xún)重寫(xiě)為:
3. 對查詢(xún)結果進(jìn)行排序
有時(shí)我們注意到,在一個(gè)表裝入初始數據后,對其發(fā)布一條SELECT * FROM tbl_name查詢(xún),檢索出的行與這些行被插入的順序是相同的。但不要認為這種情況是有規律的。如果在初始裝入表后進(jìn)行了行的刪除和插入,就會(huì )發(fā)現服務(wù)器返回表的行次序被改變了。(刪除記錄在表中留下了未使用的“空位”,MySQL 在以后插入新記錄時(shí)將會(huì )試圖對其填補。)缺省時(shí),如果選擇了行,服務(wù)器對返回行的次序不作任何保證。為了對行進(jìn)行排序,可
使用ORDER BY 子句:
在ORDER BY 子句中,可在列名之后利用ASC 或DESC 關(guān)鍵字指定排序是按該列值的升序或降序進(jìn)行的。例如,為了按倒序(降序)名排列總統名,可如下使用D E S C:
如果在ORDER BY 子句中,對某個(gè)列名既不指定ASC 又不指定D E S C,則缺省的次序為升序。在對可能包含NULL 值的列進(jìn)行排序時(shí),如果是升序排序, NULL 值出現在最前面,如果是按降序排序,NULL 值出現在最后。
查詢(xún)結果可在多個(gè)列上進(jìn)行排序,而每個(gè)列的升序或降序可以互相獨立。下面的查詢(xún)從president 表中檢索行,并按出生的州降序、在每個(gè)州中再按姓氏的升序對檢索結果進(jìn)行排序:
4. 限制查詢(xún)結果如果一個(gè)查詢(xún)返回許多行,但您只想看其中的幾行,則可以利用LIMIT 子句,特別是與ORDER BY 子句結合時(shí)更是如此。MySQL 允許限制一個(gè)查詢(xún)的輸出為前n 行。下面的查詢(xún)選擇了5 位出生日期最早的總統:
如果利用ORDER BY birth DESC 按降序排序,將得到5 位最晚出生的總統。LIMIT 也可以從查詢(xún)結果中取出中間部分。為了做到這一點(diǎn),必須指定兩個(gè)值。第一個(gè)值為結果中希望看到的第一個(gè)記錄(第一個(gè)結果記錄的編號為0 而不是1)。第二個(gè)值為希望看到的記錄個(gè)數。下面的查詢(xún)類(lèi)似于前面那個(gè)查詢(xún),但只顯示從第11 行開(kāi)始的5 個(gè)記錄:
自MySQL 3.23.2 以來(lái),可按照一個(gè)公式來(lái)排序查詢(xún)結果。例如,利用ORDER BYRAND( ) 與LIMIT 結合,從president 表中隨機抽取一個(gè)記錄:
5. 計算并命名輸出的列值
前面的多數查詢(xún)通過(guò)從表中檢索值已經(jīng)產(chǎn)生了輸出結果。MySQL 還允許作為一個(gè)公式的結果來(lái)計算輸出列的值。表達式可以簡(jiǎn)單也可以復雜。下面的查詢(xún)求一個(gè)簡(jiǎn)單表達式的值(常量)以及一個(gè)涉及幾個(gè)算術(shù)運算符和兩個(gè)函數調用的較復雜的表達式的值:
此查詢(xún)把名和姓連接起來(lái),中間間隔一個(gè)空格,將總統名形成一個(gè)單一字符串,而且將出生城市和州連接在一起,中間隔一個(gè)逗號,形成出生地。
在利用表達式來(lái)計算列值時(shí),此表達式被用作列標題。如果表達式很長(cháng)(如前面的一些查詢(xún)樣例中那樣),那么可能會(huì )出現一個(gè)很寬的列。為了處理這種情況,此列可利用AS name結構來(lái)重新命名標題。這樣的名稱(chēng)為列別名。用這種方法可使上面的輸出更有意義,如下所示:
6. 使用日期
在MySQL 中使用日期時(shí)要記住的是,在表示日期時(shí)首先給出年份。1999 年7 月27 日表示為“1 9 9 9 - 0 7 - 2 7”,而不是像通常那樣表示為“ 0 7 - 2 7 - 1 9 9 9”或“2 7 - 0 7 - 1 9 9 9”。MySQL 提供了幾種對日期進(jìn)行處理的方法??梢詫θ掌谶M(jìn)行的一些運算如下:
■ 按日期排序。(這點(diǎn)我們已經(jīng)看到幾次了。)
■ 查找特定的日期或日期范圍。
■ 提取日期值的組成部分,如年、月或日。
■ 計算日期的差。
■ 日期增加或減去一個(gè)間隔得出另一日期。
下面給出一些日期運算的例子。
為了查找特定的日期,可使用精確的日期值或與其他日期值進(jìn)行比較,將一個(gè)D ATE 列與有關(guān)的日期值進(jìn)行比較:
為了測試或檢索日期的成分,可使用諸如YEAR( )、MONTH( ) 或D AYOFMONTH( ) 這樣的函數。例如,可通過(guò)查找月份值為3 的日期,找出與筆者出生在相同月份(三月)的總統。
為了更詳細,詳細到天,可組合測試MONTH( ) 和D AYOFMONTH( ) 以找出在筆者的生日出生的總統:
這是一種可用來(lái)生成類(lèi)似報紙上娛樂(lè )部分所刊登的那種“這些人今天過(guò)生日”清單的查詢(xún)。但是,不必按前面的查詢(xún)那樣插入一個(gè)特殊的日期。為了查找每年的今天出生的總統,只要將他們的生日與C U R R E N T _ D ATE 進(jìn)行比較即可:
可從一個(gè)日期減去另一個(gè)日期。這樣可以知道日期間的間隔,這對于確定年齡是非常有用的。例如,為了確定哪位總統活得最長(cháng),可將其逝世日期減去出生日期。為此,可利用函數TO _ D AYS( ) 將出生日期和逝世日期轉換為天數,求出差,然后除以365 得出大概的年齡:
此查詢(xún)中所用的FLOOR( ) 函數截掉了年齡的小數部分,得到一個(gè)整數。得出日期之差,還可以確定相對于某個(gè)特定日期有多長(cháng)時(shí)間。這樣可以告訴歷史同盟的會(huì )員,他們還有多久就應該更新自己的會(huì )員資格了。計算他們的截止日期和當前日期之差,如果小于某個(gè)閾值,則不久就需要更新了。下面的查詢(xún)是查找需要在60 天內更新的會(huì )員:
自MySQL 3.22 以來(lái),可使用D ATE_ADD( ) 或D ATE_SUB( ) 從一個(gè)日期計算另一個(gè)日期。這些函數取一個(gè)日期及時(shí)間間隔并產(chǎn)生一個(gè)新日期。例如:
本節中前面給出的一個(gè)查詢(xún)選擇70 年代逝世的總統,它對選擇范圍的端點(diǎn)使用直接的日期值。該查詢(xún)可以利用一個(gè)字符串日期和一個(gè)由開(kāi)始日期和時(shí)間間隔計算出的結束日期來(lái)重寫(xiě):
會(huì )員更新查詢(xún)可根據D ATE_ADD( ) 寫(xiě)出如下:
本章前面給出了一個(gè)查詢(xún)如下,確定不久要來(lái)檢查但還沒(méi)來(lái)診所的牙科病人:
現在回過(guò)頭來(lái)看,讀者會(huì )更清楚這個(gè)查詢(xún)的含義了。
7. 模式匹配
MySQL 允許查找與某個(gè)模式相配的值。這樣,可以選擇記錄而不用提供精確的值。為了進(jìn)行模式匹配運算,可使用特殊的運算符( LIKE 和NOT LIKE),并且指定一個(gè)包含通配符的串。字符“_”匹配任意單個(gè)字符,而“%”匹配任意字符序列(包括空序列)。使用L I K E或NOT LIKE 的模式匹配都是不區分大小寫(xiě)的。下列模式匹配以“W”或“w”開(kāi)始的姓:
此查詢(xún)給出了一個(gè)常見(jiàn)的錯誤,它對一個(gè)算術(shù)比較運算符使用了模式。這種比較成功的惟一可能是相應的列確實(shí)包含串“ W %”或“w %”。下列模式匹配任意位置包含“W”或“w”的姓:
MySQL 還提供基于擴展正規表達式的模式匹配。正規表達式在附錄C 的REGEXP 運算符的介紹中描述。
8. 生成匯總
MySQL 所能做的最有用的事情是濃縮大量的原始數據行并對其進(jìn)行匯總。當學(xué)會(huì )了利用MySQL 來(lái)生成匯總時(shí),它就變成了用戶(hù)強有力的好幫手了,因為手工進(jìn)行匯總是一項冗長(cháng)的、費時(shí)的、易出錯的工作。匯總的一種簡(jiǎn)單的形式是確定在一組值中哪些值是唯一值。利用DISTINCT 關(guān)鍵字來(lái)刪除結果中的重復行。例如,總統出生的各個(gè)州可按如下找出:
其他的匯總形式涉及計數,可利用COUNT( ) 函數。如果使用COUNT (*),它將給出查詢(xún)所選擇的行數。如果一個(gè)查詢(xún)無(wú)WHERE 子句,COUNT(*) 將給出表中的行數。下列查詢(xún)給出共有多少人當過(guò)美國總統:
如果查詢(xún)有WHERE 子句,COUNT(*) 將給出此子句選擇多少行。下面的查詢(xún)給出目前為止對班級進(jìn)行了多少次測試:
COUNT(*) 對選中的行進(jìn)行計數。而COUNT(col_name) 只對非NULL 值進(jìn)行計數。下面的查詢(xún)說(shuō)明了這些差異:
這表示,總共有41 位總統,他們中只有一個(gè)具有名字后綴,并且大多數總統都已去世。自MySQL 3.23.2 以來(lái),可以將COUNT( ) 與DISTINCT 組合對選擇結果集中不同的值進(jìn)行計數。例如,為了對總統出生的不同州進(jìn)行計數,可執行下列查詢(xún):
可以根據匯總列中單獨的值對計數值進(jìn)行分解。例如,您可能根據下列的查詢(xún)結果知道班級中所有學(xué)生的人數:
但是,有多少是男孩?有多少是女孩?分別得出男孩、女孩的一種方法是分別對每種性別進(jìn)行計數:
雖然這個(gè)方法可行,但是它很繁鎖而且并不真正適合于可能有許多不同的值的列??紤]一下怎樣以這種方式確定每個(gè)州出生的總統人數。您不得不找出有哪些州,從而不能省略(SELECT DISTINCT state FROM president),然后對每個(gè)州執行一個(gè)SELECT COUNT(*) 查詢(xún)。很顯然,有些事是可以簡(jiǎn)化的。所幸MySQL 可以利用單個(gè)查詢(xún)對一個(gè)列中不同的值進(jìn)行計數。因此,針對學(xué)生表可以按如下得出男孩和女孩的人數:
如果以這種方法對值計數, GROUP BY 子句是必須的;它告訴MySQL 在對值計數之前怎樣進(jìn)行聚集。如果將其省去,則要出錯。COUNT(*) 與GROUP BY 一起用來(lái)對值進(jìn)行計數比分別對每個(gè)不同的列值進(jìn)行計數有更多的優(yōu)點(diǎn),這些優(yōu)點(diǎn)是:
■ 不必事先知道要匯總的列中有些什么值。
■ 不用編寫(xiě)多個(gè)查詢(xún),只需編寫(xiě)單個(gè)查詢(xún)即可。
■ 用單一查詢(xún)就可以得出所有結果,因此可以對結果進(jìn)行排序。
前兩個(gè)優(yōu)點(diǎn)對于更方便地表示查詢(xún)很重要。第三個(gè)優(yōu)點(diǎn)也較為重要,因為它提供了顯示
結果的靈活性。在使用GROUP BY 子句時(shí),其結果是在要分組的列上進(jìn)行排序的,但是可以
使用ORDER BY 來(lái)按不同的次序進(jìn)行排序。例如,如果想得到各州產(chǎn)生的總統人數,并按產(chǎn)
生人數最多的州優(yōu)先排出,可以如下使用ORDER BY 子句:
如果希望進(jìn)行排序的列是從計算得出的,則可以給該列一個(gè)別名,并在ORDER BY 子句中引用這個(gè)別名。前面的查詢(xún)說(shuō)明了這一點(diǎn); COUNT(*) 列的別名為c o u n t。引用這樣的列的另一種方法是引用它在輸出結果中的位置。前面的查詢(xún)可編寫(xiě)如下:
我不認為按位置引用列易讀。如果增加、刪除或重新排序輸出列,必須注意檢查O R D E RBY 子句,并且如果列號改變后還得記住它。別名就不存在這種問(wèn)題。如果想與計算出來(lái)的列一道使用GROUP BY,正如ORDER BY 一樣,應該利用別名或列位置來(lái)引用它。下面的查詢(xún)確定在一年的每個(gè)月中出生的總統人數:
如果不想用LIMIT 子句來(lái)限制查詢(xún)輸出,而是利用查找特定的COUNT( ) 值來(lái)達到這個(gè)目的,可使用H AVING 子句。下面的查詢(xún)給出了產(chǎn)生兩個(gè)以上總統的州:
從更為普遍的意義上說(shuō),這是一種在要查找的列中重復值時(shí)執行的查詢(xún)類(lèi)型。H AVING 類(lèi)似于W H E R E,但它是在查詢(xún)結果已經(jīng)選出后才應用的,用來(lái)縮減服務(wù)器實(shí)際送%
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Mysql入門(mén)系列:MySQL教程(2)
數據庫索引介紹及使用
MySQL 常用SQL語(yǔ)句
一千行MySQL學(xué)習筆記
新手MySQL工程師必備命令速查手冊
淺談MySQL臨時(shí)表與派生表
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久