【正文】
時(shí),可利用 AUTO_ INCREMENT屬性。 A U TO_INCREMENT 值一般從 1開(kāi)始,每行增加 1。在插入NULL 到一個(gè) A U TO _INCREMENT 列時(shí), MySQL 插入一個(gè)比該列中當(dāng)前最大值大 1 的值。一個(gè)表中最多只能有一個(gè) A U TO_INCREMENT 列。對(duì)于任何想要使用 A U TO_INCREMENT 的列,應(yīng)該定義為 NOT NULL,并定義為 P R I M A RY KEY 或定義為 UNIQUE 鍵。 ? U N S I G N E D。此屬性禁用負(fù)值。將列定義為 UNSIGNED 并不改變其基本數(shù)據(jù)類型的取值范圍;它只是前移了取值的范圍。 Creat table my_table( itiny tinyint, itiny_u tinyint unsigned)。 ? itiny 和 itiny_u 兩列都是 T I N Y I N T列,并且都可取 2 5 6個(gè)值,但是 i t i n y的取值范圍為 1 2 8 到 1 2 7,而 itiny_u 的取值范圍為 0 到 2 5 5。通過(guò)使列為 U N S I G N E D,能有效地成倍增加其取值范圍。 ? 在指定以上屬性之后(它們是專門(mén)用于數(shù)值列的),可以指定通用屬性 NULL 或N O T N U L L。如果未指定 NULL 或 NOT NULL,則缺省為 N U L L。也可以用D E FA U LT 屬性來(lái)指定一個(gè)缺省值。如果不指定缺省值,則會(huì)自動(dòng)選擇一個(gè)。對(duì)于所有數(shù)值列類型,那些可以包含 NULL 的列的缺省將為 N U L L,不能包含NULL 的列其缺省為 0。 MySQL 的列類型 ? 使用序列 ? A U TO_INCREMENT 列可提供唯一編號(hào)。這些列可自動(dòng)生成順序編號(hào)。 ? MySQL 版以前的 A U TO_INCREMENT 列的性能如下: ■ 插入 NULL 到 A U TO_INCREMENT 列,使 MySQL 自動(dòng)地產(chǎn)生下一個(gè)序列號(hào)并將此序列號(hào)自動(dòng)地插入列中。 A UTO_INCREMENT 序列從 1 開(kāi)始,因此插入表中的第一個(gè)記錄得到為 1 的序列值,而后繼插入的記錄分別得到序列值 3 等等。一般,每個(gè)自動(dòng)生成的值都比存儲(chǔ)在該列中的當(dāng)前最大值大 1。 ■ 插入 0 到 A U TO_INCREMENT 與插入 NULL 到列中的效果一樣。插入一行而不指定 A U TO_INCREMENT 列的值也與插入 NULL 的效果一樣。 MySQL 的列類型 ■如果插入一個(gè)記錄并明確指定 A U TO_INCREMENT 列的一個(gè)值,將會(huì)發(fā)生兩件事之一。如果已經(jīng)存在具有該值的某個(gè)記錄,則出錯(cuò),因?yàn)?A U TO_INCREMENT 列中的值必須是惟一的。如果不存在具有該值的記錄,那么新記錄將被插入,并且如果新記錄的 A U TO_INCREMENT 列中的值是新的最大值,那么后續(xù)行將用該值的下一個(gè)值。換句話說(shuō),也就是可以通過(guò)插入一個(gè)具有比當(dāng)前值大的序列值的記錄,來(lái)增大序列的計(jì)數(shù)器。增大計(jì)數(shù)器會(huì)使序列出現(xiàn)空白,但這個(gè)特性也有用。例如創(chuàng)建一個(gè)具有 A U TO _INCREMENT 列的表,但希望序列從 1000 而不是 1 開(kāi)始。則可以用后述的兩種辦法之一達(dá)到此目的。一個(gè)辦法是插入具有明確序列值 1000 的第一個(gè)記錄,然后通過(guò)插入 NULL 到 A U TO_INCREMENT 列來(lái)插入后續(xù)的記錄。另一個(gè)辦法是插入 A U TO_INCREMENT 列值為 999 的假記錄。然后第一個(gè)實(shí)際插入的記錄將得到一個(gè)序列號(hào) 1 0 0 0,這時(shí)再將假記錄刪除。 ■ 如果將一個(gè)不合規(guī)定的值插入 A U TO_INCREMENT 列,將會(huì)出現(xiàn)難以預(yù)料的結(jié)果。 ■ 如果刪除了在 A U TO_INCREMENT 列中含有最大值的記錄,則此值在下一次產(chǎn)生新值時(shí)會(huì)再次使用。如果刪除了表中的所有記錄,則所有值都可以重用;相應(yīng)的序列重新從 1開(kāi)始。 ■ REPLACE 語(yǔ)句正常起作用。 MySQL 的列類型 ■ U P D ATE 語(yǔ)句按類似插入新記錄的規(guī)則起作用。如果更新一個(gè) A U TO _ I N C R E M E N T列為 NULL 或 0,則會(huì)自動(dòng)將其更新為下一個(gè)序列號(hào)。如果試圖更新該列為一個(gè)已經(jīng)存在的值,將出錯(cuò)(除非碰巧設(shè)置此列的值為它所具有的值,才不會(huì)出錯(cuò),但這沒(méi)有任何意義)。如果更新該列的值為一個(gè)比當(dāng)前任何列值都大的值,則以后序列將從下一個(gè)值繼續(xù)進(jìn)行編號(hào)。 ■ 最近自動(dòng)產(chǎn)生的序列編號(hào)值可調(diào)用 L A S T _ I N S E RT_ID( ) 函數(shù)得到。它使得能在其他不知道此值的語(yǔ)句中引用 A U TO_INCREMENT 值。 L A S T _ I N S E RT_ID( ) 依賴于當(dāng)前服務(wù)器會(huì)話中生成的 A U TO_INCREMENT 值; 它不受與其他客戶機(jī)相關(guān)的 A U TO_INCREMENT 活動(dòng)的影響。如果當(dāng)前會(huì)話中沒(méi)有生成 A U TO_INCREMENT 值,則 L A S T _ I N S E RT_ID( ) 返回 0。 ? 能夠自動(dòng)生成順序編號(hào)這個(gè)功能特別有用。但是 A U TO_INCREMENT 性能有兩個(gè)缺陷。首先,序列中頂上的記錄被刪除時(shí),序列值的重用使得難于生成可能刪除和插入記錄的應(yīng)用的一系列單調(diào)(嚴(yán)格遞增)值。其次,利用從大于 1的值開(kāi)始生成序列的方法是很笨的。 MySQL 的列類型 ? MySQL 版以后的 A U TO_INCREMENT的性能進(jìn)行了下列變動(dòng)以便能夠處理上述問(wèn)題: ■ 自動(dòng)順序生成的值嚴(yán)格遞增且不重用。如果最大的值為 143 并刪除了包含這個(gè)值的記錄, MySQL 繼續(xù)生成下一個(gè)值 1 4 4。 ■ 在創(chuàng)建表時(shí),可以明確指定初始的序列編號(hào)。下面的例子創(chuàng)建一個(gè) A U TO _ I N C R E _MENT 列 seq 從 1,000,000 開(kāi)始的表: ? Create table my_table(seq int unsigned auto_increment not null primary key )auto_increment = 1000000。 ? 在使用 A U TO_INCREMENT 列時(shí),應(yīng)該記住下列要點(diǎn): ■ A U TO_INCREMENT 不是一種列類型 ,它只是一種列類型屬性。此外, A U TO _INCREMENT 是一種只能用于整數(shù)類型的屬性。 MySQL 早于 的版本并不嚴(yán)格服從這個(gè)約束,允許定義諸如 CHAR 這樣的列類型具有 A U TO_INCREMENT 屬性。但是只有整數(shù)類型作為 A U TO_INCREMENT 列正常起作用。 MySQL 的列類型 ■ A U TO_INCREMENT 機(jī)制的主要目的是生成一個(gè)正整數(shù)序列,并且如果以這種方式使用,則 A U TO_INCREMENT 列效果最好。所以應(yīng)該定義 A U TO_INCREMENT 列為 U N S I G N E D。這樣做的優(yōu)點(diǎn)是在到達(dá)列類型的取值范圍上限前可以進(jìn)行兩倍的序列編號(hào)。在某些環(huán)境下,也有可能利用 A U TO_INCREMENT 列來(lái)生成負(fù)值的序列,但是不建議這樣做。如果您決定要試一下,應(yīng)該保證進(jìn)行充分的試驗(yàn),并且在升級(jí)到不同的 MySQL 版本時(shí)需要重新測(cè)試。筆者的經(jīng)驗(yàn)表明,不同的版本中,負(fù)序列的性能并不完全一致。 ? ■ 不要認(rèn)為對(duì)某個(gè)列定義增加 A U TO_INCREMENT 是一個(gè)得到無(wú)限的編號(hào)序列的奇妙方法。事實(shí)并非這樣; A U TO_INCREMENT 序列受基礎(chǔ)列類型的取值范圍所限制。例如,如果使用 TINYINT UNSIGNED 列,則最大的序列號(hào)為 2 5 5。在達(dá)到這個(gè)界限時(shí),應(yīng)用程序?qū)㈤_(kāi)始出現(xiàn) “ 重復(fù)鍵 ” 錯(cuò)誤。 MySQL 的列類型 ? MySQL 引入了不重用序列編號(hào)的新 A U TO_INCREMENT 性能,并且允許在 C R E ATE TABLE 語(yǔ)句中指定一個(gè)初始的序列編號(hào)。這些性能在使用下列形式的 DELETE 語(yǔ)句刪除了表中所有記錄后可以撤消: ? Delete from tbl_name。 ? 在此情形下,序列重新從 1開(kāi)始而不按嚴(yán)格的增量順序繼續(xù)增加。即使在 C R E AT ETABLE 語(yǔ)句中明確指定了一個(gè)初始的序列編號(hào),相應(yīng)的序列也會(huì)從頭開(kāi)始。出現(xiàn)這種情形的原因在于 MySQL 優(yōu)化完全刪空一個(gè)表的 DELETE 語(yǔ)句的方法上;它從頭開(kāi)始重新創(chuàng)建數(shù)據(jù)文件和索引文件而不是去刪除每個(gè)記錄,這樣就丟失了所有的序列號(hào)信息。如果要?jiǎng)h除所有記錄,但希望保留序列信息,可以取消優(yōu)化并強(qiáng)制 MySQL 執(zhí)行逐行的刪除操作,如下所示: ? Delete from tbl_name where 1 0 MySQL 的列類型 ? 如果使用的是 3 . 2 3以上的版本,怎樣保持嚴(yán)格的增量序列?方法之一是保持一個(gè)只用來(lái)生成 A U TO_INCREMENT 值的獨(dú)立的表,永遠(yuǎn)不從這個(gè)表中刪除記錄。在這種情況下,獨(dú)立表中的值永遠(yuǎn)不會(huì)重用。在主表中需要生成一個(gè)新記錄時(shí),首先在序列編號(hào)表中插入一個(gè) N U L L。然后對(duì)希望包含序列編號(hào)的列使用 L A S T _ I N S E RT_ID( ) 的值將該記錄插入主表,如下所示: ? Insert into ai_tbl set ai_col=null。 ? Insert into main_tbl set id=last_insert_id().. ? 如果想要編寫(xiě)一個(gè)生成 A U TO_INCREMENT 值的應(yīng)用程序,但希望序列從 100 而不是 1開(kāi)始。 ? 如果表是空的,則插入記錄并明確地對(duì)序列編號(hào)列指定值 1 0 0。如果表不空,則對(duì)序列編號(hào)列值指定 NULL 使 MySQL 自動(dòng)生成下一個(gè)編號(hào)。 MySQL 的列類型 ? 串列類型 ? MySQL 提供了幾種存放字符數(shù)據(jù)的串類型。在某種意義上,串實(shí)際是一種 “ 通用 ” 類型,因?yàn)榭捎盟鼈儊?lái)表示任意值。例如,可用串類型來(lái)存儲(chǔ)二進(jìn)制數(shù)據(jù),如影像或聲音,或者存儲(chǔ) gzip 的輸出結(jié)果,即存儲(chǔ)壓縮數(shù)據(jù)。對(duì)于所有串類型,都要剪裁過(guò)長(zhǎng)的值使其適合于相應(yīng)的串類型。但是串類型的取值范圍很不同,有的取值范圍很小,有的則很大。取值大的串類型能夠存儲(chǔ)近 4GB 的數(shù)據(jù)。因此,應(yīng)該使串足夠長(zhǎng)以免您的信息被切斷(由于受客戶機(jī) /服務(wù)器通信協(xié)議的最大塊尺寸限制,列值的最大限額為 2 4 M B)。 ? 對(duì)于可變長(zhǎng)的列類型,各行的值所占的存儲(chǔ)量是不同的,這取決于實(shí)際存放在列中的值的長(zhǎng)度。這個(gè)長(zhǎng)度在表中用 L 表示 MySQL 的列類型 L 以外所需的額外字節(jié)為存放該值的長(zhǎng)度所需的字節(jié)數(shù)。 MySQL 通過(guò)存儲(chǔ)值的內(nèi)容及其長(zhǎng)度來(lái)處理可變長(zhǎng)度的值。這些額外的字節(jié)是無(wú)符號(hào)整數(shù)。請(qǐng)注意,可變長(zhǎng)類型的最大長(zhǎng)度、此類型所需的額外字節(jié)數(shù)以及占用相同字節(jié)數(shù)的無(wú)符號(hào)整數(shù)之間的對(duì)應(yīng)關(guān)系。例如, MEDIUMBLOB 值可能最多 22 4 1字節(jié)長(zhǎng)并需要 3 個(gè)字節(jié)記錄其結(jié)果。 3 個(gè)字節(jié)的整數(shù)類型 MEDIUMINT 的最大無(wú)符號(hào)值為 22 4 1。這并非偶然。 MySQL 的列類型 ? CHAR 和 VARCHAR 列類型 ? CHAR 和 VARCHAR 是最常使用的串類型。它們是有差異的, CHAR 是定長(zhǎng)類型而 VARCHAR 是可變長(zhǎng)類型。 CHAR(M) 列中的每個(gè)值占 M 個(gè)字節(jié);短于 M 個(gè)字節(jié)的值存儲(chǔ)時(shí)在右邊加空格(但右邊的空格在檢索時(shí)去掉)。 VARCHAR(M) 列的值只用所必需的字節(jié)數(shù)來(lái)存放(結(jié)尾的空格在存儲(chǔ)時(shí)去掉,這與 ANSI SQL 的 VARCHAR 值的標(biāo)準(zhǔn)不同),然后再加一個(gè)字節(jié)記錄其長(zhǎng)度。如果所需的值在長(zhǎng)度上變化不大,則 CHAR 是一種比 VARCHAR 好的選擇,因?yàn)樘幚硇虚L(zhǎng)度固定的表比處理行長(zhǎng)度可變的表的效率更高。如果所有的值長(zhǎng)度相同,由于需要額外的字節(jié)來(lái)記錄值的長(zhǎng)度, VARCHAR 實(shí)際占用了更多的空間。在 MySQL 以前,CHAR 和 VARCHAR 列用最大長(zhǎng)度為 1 到 255 的 M 來(lái)定義。 ? 從 MySQL 開(kāi)始, CHAR(0) 也是合法的了。在希望定義一個(gè)列,但由于尚不知道其長(zhǎng)度,所以不想給其分配空間的情況下, CHAR(0) 列作為占位符很有用處。以后可以用 A LT E RTABLE 來(lái)加寬這個(gè)列。如果允許其為 N U L L,則 CHAR(0) 列也可以用來(lái)表示 o n / o ff 值。這樣的列可能取兩個(gè)值, NULL 和空串。 CHAR(0) 列在表中所占的空間很小,只占一位。 MySQL 的列類型 ? 除少數(shù)情況外,在同一個(gè)表中不能混用 CHAR 和 VA R C H A R。 MySQL 根據(jù)情況甚至?xí)⒘袕囊环N類型轉(zhuǎn)換為另一種類型。這樣做的原因如下: ■ 行定長(zhǎng)的表比行可變長(zhǎng)的表容易處理(其理由請(qǐng)參閱 2 . 3節(jié) “ 選擇列的類型 ” )。 ■ 表行只在表中所有行為定長(zhǎng)類型時(shí)是定長(zhǎng)的。即使表中只有一列是可變長(zhǎng)的,該表的行也是可變長(zhǎng)的。 ■