MySQL數(shù)據(jù)庫(kù)中索引的創(chuàng)建與刪除
以下的文章主要是對(duì)MySQL數(shù)據(jù)庫(kù)的創(chuàng)建與刪除,以及索引與更改實(shí)際表語句的詳細(xì)解析,如果你也是MySQL數(shù)據(jù)庫(kù)的熱捧著的話,你就可以點(diǎn)擊以下的文章對(duì)其有一個(gè)更好的了解,以下就是文章的具體內(nèi)容。
一、創(chuàng)建、刪除、索引和更改表
可利用CREATE TABLE、DROP TABLE 和ALTER TABLE 語句創(chuàng)建表,然后,對(duì)它們進(jìn)行刪除,更改它們的結(jié)構(gòu)。對(duì)于它們中的每一條語句,存在MySQL數(shù)據(jù)庫(kù)專有的擴(kuò)充,這些擴(kuò)充使各語句更為有用。CREATE INDEX 和DROP INDEX 語句使您能夠增加或刪除現(xiàn)有表上
的索引。
二、CREATE TABLE 語句
用CREATE TABLE 語句創(chuàng)建表。此語句的完整語法是相當(dāng)復(fù)雜的,因?yàn)榇嬖谀敲炊嗟目蛇x子句,但在實(shí)際中此語句的應(yīng)用相當(dāng)簡(jiǎn)單。如我們?cè)诘?章中使用的所有CREATE TABLE 語句都不那么復(fù)雜。有意思的是,大多數(shù)復(fù)雜東西都是一些子句,這些子句MySQL數(shù)據(jù)庫(kù)在分析后扔掉。參閱附錄D 可看到這些復(fù)雜的東西。
看看CREATE TABLE 語句的各項(xiàng)條款,注意該語句有多少語法是用于REFERENCES CONSTRAINT 和CHECK 子句的。這些子句涉及外部鍵、引用完整性及輸入值約束。MySQL不支持這些功能,但它分析其語法使其更容易利用在其他數(shù)據(jù)庫(kù)系統(tǒng)中建立的表定義。(可以 用較少的編輯工作更容易地利用該代碼。)
如果您從頭開始編寫自己的表描述,可以完全不管這些子句。本節(jié)中我們對(duì)它們也不多做介紹。CREATE TABLE 至少應(yīng)該指出表名和表中列的清單。例如:
除構(gòu)成表的列以外,在創(chuàng)建表時(shí)還可以說明它應(yīng)該怎樣索引。另一個(gè)選擇是創(chuàng)建表時(shí)不進(jìn)行索引,以后再增加索引。如果計(jì)劃在開始將表用于查詢前,用大量的數(shù)據(jù) 填充此表,以后再創(chuàng)建索引是一個(gè)好辦法。在插入每一行時(shí)更新索引較裝載數(shù)據(jù)到一個(gè)未索引的表中然后
再創(chuàng)建索引要慢得多。我們已經(jīng)在第1章中介紹了 CREATE TABLE 語句的基本語法,并在第2章討論了怎樣描述列類型。這里假定您已經(jīng)讀過了這兩章,因此我們就不重復(fù)這些內(nèi)容了。在本節(jié)下面,我們將介紹一些 MySQL3.23 中對(duì)CREATE TABLE 語句的重要擴(kuò)充,這些擴(kuò)充在構(gòu)造表方面提供了很大的靈活性,這些擴(kuò)充為:
表存儲(chǔ)類型說明符。
僅當(dāng)表不存在時(shí)才進(jìn)行創(chuàng)建。
在客戶機(jī)會(huì)話結(jié)束時(shí)自動(dòng)刪除臨時(shí)表。
通過選擇希望表存儲(chǔ)的數(shù)據(jù)來創(chuàng)建一個(gè)表。
1. 表存儲(chǔ)類型說明符
在MySQL3.23 之前,所有用戶創(chuàng)建的表都利用的是ISAM 存儲(chǔ)方法。在MySQL3.23中,可在CREATE TABLE 語句的列的列表之后指定TYPE = type,以三種類型明確地創(chuàng)建表。其中type 可以為MYISAM、ISAM 或HEAP。例如:
將表轉(zhuǎn)換為HEAP 類型可能不是一個(gè)好主意,但是,如果希望表一直維持到服務(wù)器關(guān)閉,可以進(jìn)行這個(gè)轉(zhuǎn)換。HEAP 表在服務(wù)器退出之前,一直保留在內(nèi)存中。這三種表類型的一般特點(diǎn)如下:
MyISAM 表。MyISAM 存儲(chǔ)格式自版本3.23 以來是MySQL數(shù)據(jù)庫(kù)中的缺省類型,它有下列特點(diǎn):
如果操作系統(tǒng)自身允許更大的文件,那么文件比ISAM 存儲(chǔ)方法的大。
數(shù)據(jù)以低字節(jié)優(yōu)先的機(jī)器獨(dú)立格式存儲(chǔ)。這表示可將表從一種機(jī)器拷貝到另一種機(jī)器,即使它們的體系結(jié)構(gòu)不同也可以拷貝。
數(shù)值索引值占的存儲(chǔ)空間較少,因?yàn)樗鼈兪前锤咦止?jié)優(yōu)先存儲(chǔ)的。索引值在低位字節(jié)中變化很快,因此高位字節(jié)更容易比較。
AUTO_INCREMENT 處理比ISAM 的表更好。詳細(xì)內(nèi)容在第2章討論。
減少了幾個(gè)索引限制。例如,可對(duì)含NULL 值的列進(jìn)行索引,還可以對(duì)BLOB 和TEXT 類型的列進(jìn)行索引。
為了改善表的完整性檢查,每個(gè)表都具有一個(gè)標(biāo)志,在myisamchk 對(duì)表進(jìn)行過檢查后,設(shè)置該標(biāo)志??衫胢yisamchk – fast 跳過對(duì)自前次檢查以來尚未被修改過表的檢查,這樣使此管理任務(wù)更快。表中還有一個(gè)指示表是否正常關(guān)閉的標(biāo)志。如果服務(wù)器關(guān)閉不正常,或機(jī)器崩潰,此標(biāo)志可 用來檢測(cè)出服務(wù)器起動(dòng)時(shí)需要檢查的表。
ISAM 表。ISAM 存儲(chǔ)格式是MySQL3.23 所用的最舊的格式,但當(dāng)前仍然可用。通常,相對(duì)于ISAM 表來說,寧可使用MyISAM 表,因?yàn)樗鼈兊南拗戚^少。對(duì)ISAM 表的支持隨著此存儲(chǔ)格式被MyISAM 表格式所支持很有可能會(huì)逐漸消失。
HEAP 表。HEAP 存儲(chǔ)格式建立利用定長(zhǎng)行的內(nèi)存中的表,這使表運(yùn)行得非??臁T诜?wù)器停止時(shí),它們將會(huì)消失。在這種意義上,這些表是臨時(shí)的。但是,與用CREATE TEMPORARY TABLE 所創(chuàng)建的臨時(shí)表相比,HEAP 表是其他客戶機(jī)可見的。HEAP 表有幾個(gè)限制,這些限制對(duì)MyISAM 或ISAM 表沒有,如下所示:
索引僅用于“=”和“< = >”比較。
索引列中不能有NULL 值。
不能使用BLOB 和TEXT 列。
不能使用AUTO_INCREMENT 列。
2. 創(chuàng)建不存在的表
要?jiǎng)?chuàng)建一個(gè)不存在的表,使用CREATE TABLE IF NOT EXISTS 即可。在某種應(yīng)用程序中,無法確定要用的表是否已經(jīng)存在,因此,要?jiǎng)?chuàng)建這種表。IF NOT EXISTS 修飾符對(duì)于作為用MySQL運(yùn)行的批量作業(yè)的腳本極為有用。在這里,普通的CREATE TABLE 語句工作得
不是很好。因?yàn)樽鳂I(yè)第一次運(yùn)行 時(shí),建立這些表,如果這些表已經(jīng)存在,則第二次運(yùn)行時(shí)將出錯(cuò)。如果用IF NOT EXISTS語句,就不會(huì)有問題。每一次運(yùn)行作業(yè)時(shí),像前面一樣創(chuàng)建表。如果這些表已經(jīng)存在,在第二次運(yùn)行時(shí),創(chuàng)建表失敗,但不出錯(cuò)。這使得作業(yè)可以繼續(xù) 運(yùn)行,就像創(chuàng)建表的企圖已經(jīng)成功了一樣。
3. 臨時(shí)表
可用CREATE TEMPORARY TABLE 來創(chuàng)建臨時(shí)表,這些表在會(huì)話結(jié)束時(shí)會(huì)自動(dòng)消失。使用臨時(shí)表很方便,因?yàn)椴槐刭M(fèi)心發(fā)布DROP TABLE 語句明確地刪除這些表,而且如果您的會(huì)話不正常結(jié)束,這些表不會(huì)滯留。例如,如果某個(gè)文件中有一個(gè)用MySQL數(shù)據(jù)庫(kù)運(yùn)行的查詢,您決定不等到其結(jié)束,那么可以 在其執(zhí)行的中途停止這個(gè)查詢,而且毫無問題,服務(wù)器將刪除所創(chuàng)建的任意臨時(shí)表。在舊版的MySQL中,沒有真正的臨時(shí)表,除了您在自己的頭腦中認(rèn)為它們是 臨時(shí)的除外。
對(duì)于需要這樣的表的應(yīng)用程序,必須自己記住刪除這些表。如果忘了刪除,或在前面使其存在的客戶機(jī)中出現(xiàn)錯(cuò)誤時(shí),這些表在有人注意到并刪除它們 以前會(huì)一直存在。臨時(shí)表僅對(duì)創(chuàng)建該表的客戶機(jī)可見。其名稱可與一個(gè)現(xiàn)有的永久表相同。這不是錯(cuò)誤,也不會(huì)使已有的永久表出問題。
假如在samp_db 數(shù)據(jù)庫(kù)中創(chuàng)建了一個(gè)名為member 的臨時(shí)表。原來的member 表變成隱藏的(不可訪問),對(duì)member 的引用將引用臨時(shí)表。如果發(fā)布一條DROP TABLE member 語句,這個(gè)臨時(shí)表將被刪除,而原來的member 表“重新出現(xiàn)”。如果您簡(jiǎn)單地中斷與服務(wù)器的連接而沒有刪除臨時(shí)表,服務(wù)器會(huì)自動(dòng)地刪除它。下一次連接時(shí),
原來的member 表再次可見。名稱隱藏機(jī)制僅在一個(gè)級(jí)別上起作用。即,不能創(chuàng)建兩個(gè)具有同一個(gè)名稱的臨時(shí)表。
4. 利用SELECT 的結(jié)果創(chuàng)建表
關(guān)系數(shù)據(jù)庫(kù)的一個(gè)重要概念是,任何數(shù)據(jù)都表示為行和列組成的表,而每條SELECT 語句的結(jié)果也都是一個(gè)行和列組成的表。在許多情況下,來自SELECT 的“表”僅是一個(gè)隨著您的工作在顯示屏上滾動(dòng)的行和列的圖像。在MySQL3.23 以前,如果想將SELECT 的結(jié)果保存在一個(gè)表中以便以后的查詢使用,必須進(jìn)行特殊的安排:
1) 運(yùn)行DESCRIBE 或SHOW COLUMNS 查詢以確定想從中獲取信息的表中的列類型。
2) 創(chuàng)建一個(gè)表,明確地指定剛才查看到的列的名稱和類型。
3) 在創(chuàng)建了該表后,發(fā)布一條INSERT … SELECT 查詢,檢索出結(jié)果并將它們插入所創(chuàng)建的表中。
在MySQL3.23 中,全都作了改動(dòng)。CREATE TABLE … SELECT 語句消除了這些浪費(fèi)時(shí)間的東西,使得能利用SELECT 查詢的結(jié)果直接得出一個(gè)新表。只需一步就可以完成任務(wù),不必知道或指定所檢索的列的數(shù)據(jù)類型。這使得很容易創(chuàng)建一個(gè)完全用所喜歡的數(shù)據(jù)填充的表,并且為進(jìn) 一步查詢作了準(zhǔn)備。
可以通過選擇一個(gè)表的全部?jī)?nèi)容(無WHERE 子句)來拷貝一個(gè)表,或利用一個(gè)總是失
敗的WHERE 子句來創(chuàng)建一個(gè)空表,如:
如果希望利用LOAD DATA 將一個(gè)數(shù)據(jù)文件裝入原來的文件中,而不敢肯定是否具有指定的正確數(shù)據(jù)格式時(shí),創(chuàng)建空拷貝很有用。您并不希望在第一次未得到正確的選項(xiàng)時(shí)以原來表中畸形的記 錄而告終。
利用原表的空拷貝允許對(duì)特定的列和行分隔符用LOAD DATA 的選項(xiàng)進(jìn)行試驗(yàn),直到對(duì)輸入數(shù)據(jù)的解釋滿意時(shí)為止。在滿意之后,就可以將數(shù)據(jù)裝入原表了。
可結(jié)合使用CREATE TEMPORARY TABLE 與SELECT 來創(chuàng)建一個(gè)臨時(shí)表作為它自身的拷貝,如:
這允許修改my_tbl 的內(nèi)容而不影響原來的內(nèi)容。在希望試驗(yàn)對(duì)某些修改表內(nèi)容的查詢,而又不想更改原表內(nèi)容時(shí),這樣做很有用。為了使用利用原表名的預(yù)先編寫的腳本,不需要為引 用不同的表而編輯這些腳本;只需在腳本的起始處增加CREATE TEMPORARY TABLE語句即可。相應(yīng)的腳本將創(chuàng)建一個(gè)臨時(shí)拷貝,并對(duì)此拷貝進(jìn)行操作,當(dāng)腳本結(jié)束時(shí)服務(wù)器會(huì)自動(dòng)刪除這個(gè)拷貝。
要?jiǎng)?chuàng)建一個(gè)作為自身的空拷貝的表,可以與CREATE TEMPORARY … SELECT 一起使用WHERE 0 子句,例如:
但創(chuàng)建空表時(shí)有幾點(diǎn)要注意。在創(chuàng)建一個(gè)通過選擇數(shù)據(jù)填充的表時(shí),其列名來自所選擇的列名。如果某個(gè)列作為表達(dá)式的結(jié)果計(jì)算,則該列的“名稱”為表達(dá)式的文 本。表達(dá)式不是合法的列名,可在MySQL數(shù)據(jù)庫(kù)中運(yùn)行下列查詢了解這一點(diǎn):
如果選擇了來自不同表的具有相同名稱的列,將會(huì)出現(xiàn)一定的困難。假定表t1和t2 兩者都具有列c,而您希望創(chuàng)建一個(gè)來自兩個(gè)表中行的所有組合的表。
那么可以提供別名指定新表中惟一性的列名,如:
通過選擇數(shù)據(jù)進(jìn)行填充來創(chuàng)建一個(gè)表并會(huì)自動(dòng)拷貝原表的索引。
3、 DROP TABLE 語句
刪 除表比創(chuàng)建表要容易得多,因?yàn)椴恍枰付ㄓ嘘P(guān)其內(nèi)容的任何東西;只需指定其名稱即可,如:
- DROP TABLE tb1_name
MySQL對(duì)DROP TABLE 語句在某些有用的方面做了擴(kuò)充。首先,可在同一語句中指定幾個(gè)表對(duì)它們進(jìn)行刪除,如:
- DROP TABLE tb1_name1,tb1_name2,……
其次,如果不能肯定一個(gè)表是否存在,但希望如果它存在就刪除它。那么可在此語句中增加IF EXISTS。這樣,如果DROP TABLE 語句中給出的表不存在,MySQL不會(huì)發(fā)出錯(cuò)誤信息。如:
- DROP TABLE IF EXISTS tb1_name
IF EXISTS 在MySQL所用的腳本中很有用,因?yàn)槿笔∏闆r下, MySQL將在出錯(cuò)時(shí)退出。例如,有一個(gè)安裝腳本能夠創(chuàng)建表,這些表將在其他腳本中繼續(xù)使用。在此情形下,希望保證此創(chuàng)建表的腳本在開始運(yùn)行時(shí)無后顧之 憂。如果在該腳本開始處使用普通的DROP TABLE,那么它在第一次運(yùn)行時(shí)將會(huì)失敗,因?yàn)檫@些表從未創(chuàng)建過。如果使用IF EXISTS,就不會(huì)產(chǎn)生問題了。當(dāng)表已經(jīng)存在時(shí),將它們刪除;如果不存在,腳本繼續(xù)運(yùn)行。
四. 創(chuàng)建和刪除索引
索引是加速表內(nèi)容訪問的主要手段,特別對(duì)涉及多個(gè)表的連接的查詢更是如此。這是第4章“查詢優(yōu)化”中的一個(gè)重要內(nèi)容,第4章討論了為什么需要索引,索引如 何工作以及怎樣利用它們來優(yōu)化查詢。本節(jié)中,我們將介紹索引的特點(diǎn),以及創(chuàng)建和刪除索引的語法。
1. 索引的特點(diǎn)
MySQL對(duì)構(gòu)造索引提供了很大的靈活性??蓪?duì)單列或多列的組合進(jìn)行索引。如果希望能夠從一個(gè)表的不同列中找出一個(gè)值,還可以在一個(gè)表上構(gòu)造不止一個(gè)索 引。如果某列為串類型而非ENUM 或SET 類型,可以選擇只對(duì)該列最左邊的n 個(gè)字符進(jìn)行索引。如果該列的前n個(gè)字符最具有唯一性,這樣做一般不會(huì)犧牲性能,而且還會(huì)對(duì)性能有大的改善:用索引列的前綴而非整個(gè)列可使索引更小且訪問更 快。雖然隨著MySQL數(shù)據(jù)庫(kù)的進(jìn)一步開發(fā)創(chuàng)建索引的約束將會(huì)越來越少,但現(xiàn)在還是存在一些約束的。下面的表根據(jù)索引的特性,給出了ISAM 表和MyISAM 表之間的差別:
從此表中可以看到,對(duì)于ISAM 表來說,其索引列必須定義為NOT NULL,并且不能對(duì)BLOB 和TEXT 列進(jìn)行索引。MyISAM 表類型去掉了這些限制,而且減緩了其他的一些限制。兩種表類型的索引特性的差異表明,根據(jù)所使用的MySQL版本的不同,有可能對(duì)某些列不能進(jìn)行索引。例 如,如果使用3.23 版以前的版本,則不能對(duì)包含NULL 值的列進(jìn)行索引。
如果使用的是MySQL3.23版或更新的版本,但表是過去以ISAM 表創(chuàng)建的,可利用ALTER TABLE 很方便地將它們轉(zhuǎn)換為MyISAM 存儲(chǔ)格式,這樣使您能利用某些較新的索引功能,如:
ALTER TABLE tb1_name TYPE=MYISAM
2. 創(chuàng)建索引
在執(zhí)行CREATE TABLE 語句時(shí),可為新表創(chuàng)建索引,也可以用CREATE INDEX 或ALTER TABLE 來為一個(gè)已有的表增加索引。CREATE INDEX 是在MySQL3.23版中引入的,但如果使用3.23 版以前的版本,可利用ALTER TABLE 語句創(chuàng)建索引(MySQL通常在內(nèi)部將CRE ATE INDEX 映射到ALTER TABLE)。可以規(guī)定索引能否包含重復(fù)的值。如果不包含,則索引應(yīng)該創(chuàng)建為PRIMARY KEY 或UNIQUE 索引。對(duì)于單列惟一索引,這保證了列不包含重復(fù)的值。對(duì)于多列惟一索引,它保證值的組合不重復(fù)。
PRIMARY KEY 索引和UNIQUE 索引非常類似。事實(shí)上, PRIMARY KEY 索引僅是一個(gè)具有名稱PRIMARY 的UNIQUE 索引。這表示一個(gè)表只能包含一個(gè)PRIMARY KEY,因?yàn)橐粋€(gè)表中不可能具有兩個(gè)同名的索引。同一個(gè)表中可有多個(gè)UNIQUE 索引,雖然這樣做意義不
大。
為了給現(xiàn)有的表增加一個(gè)索引,可使用ALTER TABLE 或CREATE INDEX 語句。ALTER TABLE 最常用,因?yàn)榭捎盟鼇韯?chuàng)建普通索引、UNIQUE 索引或PRIMARY KEY 索引,如:
其中tbl_name 是要增加索引的表名,而column_list 指出對(duì)哪些列進(jìn)行索引。如果索引由不止一列組成,各列名之間用逗號(hào)分隔。索引名index_name 是可選的,因此可以不寫它,MySQL將根據(jù)第一個(gè)索引列賦給它一個(gè)名稱。ALTER TABLE 允許在單個(gè)語句中指定多個(gè)表的更改,因此可以在同時(shí)創(chuàng)建多個(gè)索引。
CREATE INDEX 可對(duì)表增加普通索引或UNIQUE 索引,如:
tbl _ name、index_name 和column_list 具有與ALTER TABLE 語句中相同的含義。這里索引名不可選。不能用CREATE INDEX 語句創(chuàng)建PRIMARY KEY 索引。要想在發(fā)布CREATE TABLE 語句時(shí)為新表創(chuàng)建索引,所使用的語法類似于ALTER TABLE 語句的語法,但是應(yīng)該在您定義表列的語句部分指定索引創(chuàng)建子句,如下所示:
與ALTER TABLE 一樣,索引名對(duì)于INDEX 和UNIQUE 都是可選的,如果未給出,MySQL數(shù)據(jù)庫(kù)將為其選一個(gè)。有一種特殊情形:可在列定義之后增加PRIMARY KEY 創(chuàng)建一個(gè)單列的PRIMARY KEY索引,如下所示:
前面所有表創(chuàng)建樣例都對(duì)索引列指定了NOT NULL。如果是ISAM 表,這是必須的,因?yàn)椴荒軐?duì)可能包含NULL 值的列進(jìn)行索引。如果是MyISAM 表,索引列可以為NULL,只要該索引不是PRIMARY KEY 索引即可。
如果對(duì)某個(gè)串列的前綴進(jìn)行索引(列值的最左邊n 個(gè)字符),應(yīng)用column_list 說明符表示該列的語法為col_name(n) 而不用c o l _ name。例如,下面第一條語句創(chuàng)建了一個(gè)具有兩個(gè)CHAR 列的表和一個(gè)由這兩列組成的索引。第二條語句類似,但只對(duì)每個(gè)列的前綴進(jìn)行索引:
在某些情況下,可能會(huì)發(fā)現(xiàn)必須對(duì)列的前綴進(jìn)行索引。例如,索引行的長(zhǎng)度有一個(gè)最大上限,因此,如果索引列的長(zhǎng)度超過了這個(gè)上限,那么就可能需要利用前綴進(jìn) 行索引。在MyISAM 表索引中,對(duì)BLOB 或TEXT 列也需要前綴索引。對(duì)一個(gè)列的前綴進(jìn)行索引限制了以后對(duì)該列的更改;不能在不刪除該索引并使用較短前綴的情況下,將該列縮短為一個(gè)長(zhǎng)度小于索引所用前綴的 長(zhǎng)度的列。
3. 刪除索引
可利用DROP INDEX 或ALTER TABLE 語句來刪除索引。類似于CREATE INDEX 語句,DROP INDEX 通常在內(nèi)部作為一條ALTER TABLE 語句處理,并且DROP INDEX 是在MySQL3.22 中引入的。刪除索引語句的語法如下:
前兩條語句是等價(jià)的。第三條語句只在刪除PRIMARY KEY 索引時(shí)使用;在此情形中,不需要索引名,因?yàn)橐粋€(gè)表只可能具有一個(gè)這樣的索引。如果沒有明確地創(chuàng)建作為PRIMARY KEY 的索引,但該表具有一個(gè)或多個(gè)UNIQUE 索引,則MySQL將刪除這些UNIQUE 索引中的第一個(gè)。
如果從表中刪除了列,則索引可能會(huì)受到影響。如果所刪除的列為索引的組成部分,則該列也會(huì)從索引中刪除。如果組成索引的所有列都被刪除,則整個(gè)索引將被刪 除。
五.ALTER TABLE 語句
ALTER TABLE 語句是MySQL中一條通用的語句,可用它來做許多事情。我們已經(jīng)看過了它的幾種功能(創(chuàng)建和刪除索引以及將表從一種存儲(chǔ)格式轉(zhuǎn)換為另一種存儲(chǔ)格式)。本 節(jié)中,我們將介紹它的一些其他功能。ALTER TABLE 的完整語法在附錄D 中介紹。
在發(fā)現(xiàn)某個(gè)表的結(jié)構(gòu)不再反映所希望的東西時(shí), ALTER TABLE很有用處。可能希望用該表記錄其他信息,或者它含有多余的值。或者有的列太小,或者其定義較實(shí)際需要來說太大,需要將它們改小以節(jié)省存儲(chǔ)空間。 或者發(fā)布CREATE TABLE 語句時(shí)給出的表名不對(duì)。等等,諸如此類的問題,都可以用ALTER TABLE 語句來解決。下面是一些例子:
您正操縱一個(gè)基于Web 的問卷,將每份提交的問卷作為表中的一個(gè)記錄。后來決定修改此問卷,增加一些問題。這時(shí)必須對(duì)表增加一些列以存放新問題。
您正在管理一個(gè)研究項(xiàng)目。用AUTO_INCREMENT 列分配案例號(hào)來研究記錄。您不希望經(jīng)費(fèi)延期太長(zhǎng)產(chǎn)生多于50 000 個(gè)以上的記錄,因此,令該列的類型為UNSIGNED SMALLINT,它能存儲(chǔ)的最大惟一值為65 535。但是,項(xiàng)目的經(jīng)費(fèi)延長(zhǎng)了,似乎可能另外產(chǎn)生50 000 個(gè)記錄。這時(shí),需要使該列的類型更大一些以便存儲(chǔ)更多的件號(hào)。
大小的更改也可能是反方向的。可能創(chuàng)建了一個(gè)CHAR(255) 列,但現(xiàn)在發(fā)現(xiàn)表中沒有比100 個(gè)字符更長(zhǎng)的串。這時(shí)可縮短該列以節(jié)省存儲(chǔ)空間。ALTER TABLE 的語法如下:
每個(gè)action 表示對(duì)表所做的一個(gè)修改。MySQL數(shù)據(jù)庫(kù)擴(kuò)充了ALTER TABLE 語句,允許指定多個(gè)動(dòng)作,各動(dòng)作間以逗號(hào)分隔。這對(duì)于減少鍵盤輸入很有用,但這個(gè)擴(kuò)充的更為重要的原因是,除非能同時(shí)將所有VARCHAR 列更改為CHAR 列,否則不可能將表從行可變長(zhǎng)的表更改為行定長(zhǎng)的表。
下面的例子示出了某些ALTER TABLE 的功能。
對(duì)表重新命名。這很簡(jiǎn)單;只需給出舊表名和新表名即可:
在MySQL3.23 中有臨時(shí)表,重命名一個(gè)臨時(shí)表為數(shù)據(jù)庫(kù)中已經(jīng)存在的名稱將隱藏原始表,只要臨時(shí)表存在就會(huì)隱藏原始表。這類似于通過用相同的名字創(chuàng)建一個(gè)臨時(shí)表來隱藏一個(gè) 表的方法。
更改列類型。為了更改列的類型,可使用CHANGE 或MODIFY 子句。假如表my _ t b l中的列為SMALLINT UNSIGNED 的,希望將其更改為MEDIUMINT UNSIGNED 的列。用下面的任何一個(gè)命令都可完成此項(xiàng)工作:
為什么在CHANGE 命令中給出列名兩次?因?yàn)镃HANGE 可以做的而MODIFY 不能做的一樁事是,除了更改類型外還能更改列名。如果希望在更改類型的同時(shí)重新將i 命名為j,可按如下進(jìn)行:
重要的是命名了希望更改的列,并說明了一個(gè)包括列名的列的完整定義。即使不更改列名,也需要在定義中包括相應(yīng)的列名。
更改列類型的一個(gè)重要原因是為了改善比較兩個(gè)表的連接查詢的效率。在兩個(gè)列的類型相同時(shí),比較更快。假如執(zhí)行如下的查詢:
如果t1.name 為CHAR( 10 ),而t2.name 為CHAR( 15 ),此查詢的運(yùn)行速度沒有它們兩者都為CHAR(15) 時(shí)的快。那么可以用下面的任一條命令更改t1.name 使它們的類型相同:
對(duì)于3 . 2 3以前的MySQL版本,所連接的列必須是同樣類型的這一點(diǎn)很重要,否則索引不能用于比較。對(duì)于版本3.23 或以上的版本,索引可用于不同的類型,但如果類型相同,查詢?nèi)匀桓臁?/p>
將表從可變長(zhǎng)行轉(zhuǎn)換為定長(zhǎng)行。假如有一個(gè)表chartbl 具有VARCHAR 列,想要把它轉(zhuǎn)換為CHAR 列,看看能夠得到什么樣的性能改善。(定長(zhǎng)行的表一般比變長(zhǎng)行的表處理更快。)這個(gè)表如下創(chuàng)建:
這里的問題是需要在相同的ALTER TABLE 語句中一次更改所有的列。不可能一次一列地改完,或者說這個(gè)企圖將不起作用。如果執(zhí)行DESCRIBE chartbl,會(huì)發(fā)現(xiàn)兩個(gè)列仍然是VARCHAR 的列!原因是如果每次更改一列, MySQL注意到表仍然包含有可變長(zhǎng)的列,則會(huì)把已經(jīng)更改過的列重新轉(zhuǎn)換為VARCHAR 以節(jié)省空間。為了處理這個(gè)問題,應(yīng)該同時(shí)更改所有VARCHAR 列:
現(xiàn)在DESCRIBE 將顯示該表包含的都是CHAR 列。確實(shí),這種類型的操作很重要,因?yàn)樗笰LTER TABLE 能在相同的語句中支持多個(gè)動(dòng)作。
這里要注意,在希望轉(zhuǎn)換這樣的表時(shí):如果表中存在BLOB 或TEXT 列將使轉(zhuǎn)換表為定長(zhǎng)行格式的企圖失敗。即使表中只有一個(gè)可變長(zhǎng)的列都將會(huì)使表有可變長(zhǎng)的行,因?yàn)檫@些可變長(zhǎng)的列類型沒有定長(zhǎng)的等價(jià)物。
將表從定長(zhǎng)行轉(zhuǎn)換為可變長(zhǎng)的行。雖然, chartbl 用定長(zhǎng)行更快,但它要占用更多的空間,因此決定將它轉(zhuǎn)換回原來的形式以節(jié)省空間。這種轉(zhuǎn)換更為容易。只需將某個(gè)CHAR 列轉(zhuǎn)換為VARCHAR 列,MySQL數(shù)據(jù)庫(kù)就自動(dòng)地轉(zhuǎn)換其他的CHAR 列。要想轉(zhuǎn)換chartbl 表,用下列任一條語句都可以:
轉(zhuǎn)換表的類型。如果從MySQL3.23 版以前的版本升級(jí)到3.23 版或更高,那么可能會(huì)有一些原來創(chuàng)建為ISAM 表的舊表。如果希望使它們?yōu)镸yISAM 格式,如下操作:
為什么要這樣做呢?正如在“創(chuàng)建和刪除索引”小節(jié)中所介紹的那樣,一個(gè)原因是MyISAM 存儲(chǔ)格式具有某些ISAM 格式?jīng)]有的索引特性,例如能夠?qū)ULL 值、BLOB 和TEXT 列類型進(jìn)行索引。另一個(gè)原因?yàn)椋?MyISAM 表是獨(dú)立于機(jī)器的,因此可通過將它們直接拷貝來將它們移到其他機(jī)器上,即使那些機(jī)器具有不同的硬件體系結(jié)構(gòu)也同樣。這在第11章中將要作進(jìn)一步的介紹。
【編輯推薦】
- MySQL數(shù)據(jù)庫(kù)進(jìn)行備份在Linux異構(gòu)網(wǎng)絡(luò)里
- 卸載MySQL數(shù)據(jù)庫(kù)的實(shí)現(xiàn)需要哪些項(xiàng)目?
- 圖解MySQL數(shù)據(jù)庫(kù)安裝與實(shí)際操作
- 從MySQL數(shù)據(jù)庫(kù)表中來檢索數(shù)據(jù)并不難
- MySQL數(shù)據(jù)庫(kù)訪問妙招在Linux之下