1. 主鍵約束
主鍵就是表中的一列或多個列的一組,其值能唯一地標志表中的每一行。通過定義PRIMARY KEY約束來創建主鍵,而且PRIMARY KEY約束中的列不能取空值。由於PRIMARY KEY約束能確保數據的唯一,所以經常用來定義標志列。當為表定義PRIMARY KEY約束時,MySQL為主鍵列創建唯一性索引,實現數據的唯一性,在查詢中使用主鍵時,該索引可用來對數據進行快速訪問。如果 PRIMARY KEY 約束是由多列組合定義的,則某一列的值可以重復,但PRIMARY KEY 約束定義中所有列的組合值必須唯一。
可以用兩種方式定義主鍵:作為列或表的完整性約束。作為列的完整性約束時,只需在列定義的時候加上關鍵字PRIMARY KEY,作為表的完整性約束時,需要在語句最後加上一條PRIMARY KEY(col_name,…)語句。
例: 創建表XS1,將姓名定義為主鍵。
CREATE TABLE XS1(
學號 varchar(6) NULL,
姓名 varchar(8) NOT NULL PRIMARY KEY ,
出生日期 datetime ); www.2cto.com
說明:例中主鍵定義於空指定之後,空指定也可以在主鍵之後指定.
當表中的主鍵為復合主鍵時(即兩個字段是主鍵時),只能定義為表的完整性約束。
例: 創建course表來記錄每門課程的學生學號、姓名、課程號、學分和畢業日期。其中學號、課程號和畢業日期構成復合主鍵。
CREATE TABLE course(
學號 varchar(6) NOT NULL,
姓名 varchar(8) NOT NULL,
畢業日期 date NOTNULL,
課程號 varchar(3) ,
學分 tinyint ,
PRIMARY KEY (學號, 課程號, 畢業日期));
如果作為主鍵的一部分的一個列沒有定義為NOT NULL,MySQL就自動把這個列定義為NOT NULL。實際上,在例中,可以忽略姓名列中的NOT NULL聲明,但是為了清楚起見,最好包含這個空指定。
2. 原則上,任何列或者列的組合都可以充當一個主鍵。制定但是主鍵列必須遵守一些規則。這些規則源自於關系模型理論和MySQL所的規則:
(1)每個表只能定義一個主鍵。來自關系模型的這一規則也適用於MySQL。
(2)關系模型理論要求必須為每個表定義一個主鍵。然而,MySQL並不要求這樣,可以創建一個沒有主鍵的表。但是,從安全角度應該為每個基礎表指定一個主鍵。主要原因在於,沒有主鍵,可能在一個表中存儲兩個相同的行。因此,兩個行不能彼此區分。在查詢過程中,它們將會滿足同樣的條件,在更新的時候也總是一起更新,可能會導致數據庫崩潰。
(3)表中的兩個不同的行在主鍵上不能具有相同的值。這就是唯一性規則。
(4)如果從一個復合主鍵中刪除一列後,剩下的列構成主鍵仍然滿足唯一性原則,那麼,這個復合主鍵是不正確的,這條規則稱為最小化規則(minimality rule)。也就是說,復合主鍵不應該包含一個不必要的列。
(5)一個列名在一個主鍵的列列表中只能出現一次。
MySQL自動地為主鍵創建一個索引。通常,這個索引名為PRIMARY。然而,可以重新給這個索引起名。
例: 創建例5.9中的course表,把主鍵創建的索引命名為INDEX_course。
www.2cto.com
CREATE TABLE course(
學號 varchar(6) NOT NULL,
姓名 varchar(8) NOT NULL,
學分 tinyint ,
PRIMARY KEY INDEX_course(學號, 課程號));
3. 替代鍵約束(unique)
在關系模型中,替代鍵像主鍵一樣,是表的一列或一組列,它們的值在任何時候都是唯一的。替代鍵是沒有被選做主鍵的候選鍵。定義替代鍵的關鍵字是UNIQUE。
例: 在表XS1中將姓名列定義為一個替代鍵。
CREATE TABLE XS1(
學號 varchar(6) NULL,
姓名 varchar(8) NOT NULLUNIQUE,
出生日期 datetime NULL,
PRIMARY KEY(學號));
說明:關鍵字UNIQUE表示“姓名”是一個替代鍵,其列值必須是唯一的。
替代鍵也可以定義為表的完整性約束,前面語句可以這樣定義:
CREATE TABLE XS1(
學號 varchar(6) NULL,
姓名 varchar(8) NOTNULL,
出生日期 datetime NULL,
PRIMARY KEY(學號),
UNIQUE(姓名));
4.在MySQL中替代鍵和主鍵的區別主要有以下幾點。
(1)一個數據表只能創建一個主鍵。但一個表可以有若干個UNIQUE鍵,並且它們甚至可以重合,例如,在C1和C2列上定義了一個替代鍵,並且在C2和C3上定義了另一個替代鍵,這兩個替代鍵在C2列上重合了,而MySQL允許這樣。 www.2cto.com
(2)主鍵字段的值不允許為NULL,而UNIQUE字段的值可取NULL,但是必須使用NULL或NOTNULL聲明。
(3)一般創建PRIMARY KEY約束時,系統會自動產生PRIMARY KEY索引。創建UNIQUE約束時,系統自動產生UNIQUE索引。
通過PRIMERY KEY約束和UNIQUE約束可以實現表的所謂實體完整性約束。定義為PRIMERY KEY和UNIQUE KEY的列上都不允許出現的值。
5.外鍵(foreign)
參照完整性約束(referential integrity constraint)是一種特殊的完整性約束,實現為一個外鍵。所以XS_KC表中的學號列和課程號列都可以定義為一個外鍵。可以在創建表或修改表時定義一個外鍵聲明。
定義外鍵的語法格式已經在介紹索引時給出了,這裡列出reference_definition的定義。語法格式如下:
REFERENCES tbl_name [(index_col_name,...)]
[ON DELETE {RESTRICT | CASCADE |SET NULL | NO ACTION}]
[ON UPDATE {RESTRICT | CASCADE |SET NULL | NO ACTION}]
說明:外鍵被定義為表的完整性約束,reference_definition中包含了外鍵所參照的表和列,還可以聲明參照動作。
● tb1_name:外鍵所參照的表名,這個表叫做被參照表。而外鍵所在的表叫做參照表。
● index_col_name:格式為col_name[(length)] [ASC | DESC]
col_name:被參照的列名。外鍵可以引用一個或多個列,外鍵中的所有列值在引用的列中必須全部存在。外鍵可以只引用主鍵和替代鍵。外鍵不能引用被參照表中隨機的一組列,它必須是被參照表的列的一個組合且其中的值都保證是唯一的。
● ON DELETE | ONUPDATE:可以為每個外鍵定義參照動作。參照動作包含兩部分:
在第一部分中,指定這個參照動作應用哪一條語句。這裡有兩條相關的語句,即UPDATE和DELETE語句;
在第二部分中,指定采取哪個動作。可能采取的動作是restrict、cascade、SET NULL、NO ACTION和SETDEFAULT。接下來說明這些不同動作的含義。
RESTRICT:當要刪除或更新父表中被參照列上在外鍵中出現的值時,拒絕對父表的刪除或更新操作。
CASCADE:從父表刪除或更新行時自動刪除或更新子表中匹配的行。
SET NULL:當從父表刪除或更新行時,設置子表中與之對應的外鍵列為NULL。如果外鍵列沒有指定NOT NULL限定詞,這就是合法的。
NO ACTION:NO ACTION意味著不采取動作,就是如果有一個相關的外鍵值在被參考的表裡,刪除或更新父表中主要鍵值的企圖不被允許,和RESTRICT一樣。
SET DEFAULT:作用和SET NULL一樣,只不過SET DEFAULT是指定子表中的外鍵列為默認值。
如果沒有指定動作,兩個參照動作就會默認地使用RESTRICT。
外鍵目前只可以用在那些使用InnoDB存儲引擎創建的表中,對於其他類型的表,MySQL服務器能夠解析CREATE TABLE語句中的FOREIGN KEY語法,但不能使用或保存它。
例: 創建XS1表,所有的XS表中學生學號都必須出現在XS1表中,假設已經使用學號列作為主鍵創建了XS表。
www.2cto.com
CREATE TABLE XS1(
學號 varchar(6) NULL,
姓名 varchar(8) NOTNULL,
出生日期 datetime NULL,
PRIMARY KEY (姓名),
FOREIGN KEY (學號) REFERENCES XS (學號)
ONDELETE RESTRICT ON UPDATE RESTRICT);
6.當指定一個外鍵的時候,以下的規則適用:
(1)被參照表必須已經用一條CREATE TABLE語句創建了,或者必須是當前正在創建的表。在後一種情況下,參照表是同一個表。
(2)必須為被參照表定義主鍵。
(3)必須在被參照表的表名後面指定列名(或列名的組合)。這個列(或列組合)必須是這個表的主鍵或替代鍵。
(4)盡管主鍵是不能夠包含空值的,但允許在外鍵中出現一個空值。這意味著,只要外鍵的每個非空值出現在指定的主鍵中,這個外鍵的內容就是正確的。
(5)外鍵中的列的數目必須和被參照表的主鍵中的列的數目相同。
(6)外鍵中的列的數據類型必須和被參照表的主鍵中的列的數據類型對應相等。
與外鍵相關的被參照表和參照表可以是同一個表。這樣的表稱為自參照表(self-referencing table),這種結構稱為自參照完整性(self-referentialintegrity)。
例如,可以創建這樣的XS1表:
CREATE TABLE XS1(
學號 varchar(6) NOTNULL,
姓名 varchar(8) NOTNULL,
出生日期 datetime NULL,
PRIMARY KEY (學號),
FOREIGN KEY (學號) REFERENCES XS1 (學號));
www.2cto.com
7. check約束
每個數據庫都還有一些專用的完整性約束。例如,KC表中星期數要在1~7之間,XS表中出生日期必須大於1986年1月1日。這樣的規則可以使用CHECK完整性約束來指定。
CHECK完整性約束在創建表的時候定義。可以定義為列完整性約束,也可以定義為表完整性約束。語法格式為: CHECK(expr)
說明:expr是一個表達式,指定需要檢查的條件,在更新表數據的時候,MySQL會檢查更新後的數據行是否滿足CHECK的條件。
例1: 創建表student,只考慮學號和性別兩列,性別只能包含男或女。
CREATE TABLE student(
學號 char(6) NOT NULL,
性別 char(1) NOT NULL
CHECK(性別 IN ('男', '女')));
這裡CHECK完整性約束指定了性別允許哪個值,由於CHECK包含在列自身的定義中,所以CHECK完整性約束被定義為列完整性約束。
例2: 創建表student1,只考慮學號和出生日期兩列,出生日期必須大於1980年1月1日。
CREATE TABLE student1(
學號 char(6) NOT NULL,
出生日期 date NOT NULL
CHECK(出生日期>'1980-01-01'));
前面的CHECK完整性約束中使用的表達式都很簡單,MySQL還允許使用更為復雜的表達式。例如,可以在條件中加入子查詢。
例: 創建表student2,只考慮學號和性別兩列,並且確認性別列中的所有值來源於student表的性別列中。
CREATE TABLE student2(
學號 char(6) NOT NULL,
性別 char(1) NOT NULL
CHECK( 性別 IN (SELECT 性別 FROM student)));
如果指定的完整性約束中,要相互比較一個表的兩個或多個列,那麼該列完整性約束必須定義表完整性約束。
例: 創建表student3,有學號、最好成績和平均成績3列,要求最好成績必須大於平均成績。
CREATE TABLE student3( www.2cto.com
學號 char(6) NOT NULL,
最好成績 INT(1) NOT NULL,
平均成績 INT(1) NOT NULL,
CHECK(最好成績>平均成績));
也可以同時定義多個CHECK完整性約束,中間用逗號隔開。
然而,不幸的是,在目前的MySQL版本中,CHECK完整性約束還沒有被強化,上面例子中定義的CHECK約束會被MySQL分析,但會被忽略,也就是說,這裡的CHECK約束暫時只是一個注釋,不會起任何作用。相信在未來的版本中它能得到擴展。
8. CONSTRAINT關鍵字
如果一條INSERT、UPDATE或DELETE語句違反了完整性約束,則MySQL返回一條出錯消息並且拒絕更新,一個更新可能會導致多個完整性約束的違反。在這種情況下,應用程序獲取幾條出錯消息。為了確切地表示是違反了哪一個完整性約束,可以為每個完整性約束分配一個名字,隨後,出錯消息包含這個名字,從而使得消息對於應用程序更有意義。
constraint關鍵字用來指定完整性約束的名字。語法格式為:
CONSTRAINT [symbol]
symbol為指定的名字,這個名字在完整性約束的前面被定義,在數據庫裡這個名字必須是唯一的。如果它沒有被給出,則MySQL自動創建這個名字。只能給表完整性約束指定名字,而無法給列完整性約束指定名字。
例: 創建與例5.8中相同的XS1表,並為主鍵命名。
CREATE TABLE XS1(
學號 varchar(6) NULL,
姓名 varchar(8) NOT NULL,
出生日期 datetime NULL www.2cto.com
CONSTRAINTPRIMARY_KEY_XS1 PRIMARY KEY(姓名));
說明:本例中給主鍵姓名分配了名字PRIMARY_KEY_XS1。
在定義完整性約束的時候應當盡可能地分配名字,以便在刪除完整性約束的時候,可以更容易地引用它們。這意味著,表完整性約束比列完整性約束更受歡迎,因為不可能為後者分配一個名字。
9. DROP TABLE語句(刪除)
如果使用一條DROP TABLE語句刪除一個表,所有的完整性約束都自動被刪除了。被參照表的所有外鍵也都被刪除了,使用ALTER TABLE語句,完整性可以獨立地被刪除,而不用去刪除表本身。刪除的語法和刪除索引的語法一樣。
例: 刪除表XS的主鍵。
ALTER TABLE XS DROP PRIMARY KEY;
作者 tianyazaiheruan