MySQL中外鍵(FROEIGN KEY)的使用


MySQL中外鍵(FROEIGN KEY)的使用

1.定義:

外鍵用來在兩個表的數據之間建立鏈接,它可以是一列或者多列;一個表可以有一個或多個外鍵。

外鍵對應的是參照完整性,一個表的外鍵可以為空值,若不為空值,則每一個外鍵值必須等於另一個表中主鍵的某個值。

外鍵是表的一個字段,不是表的主鍵,但對應另一個表的主鍵;定義外鍵后,不允許刪除另一個表中具有關聯關系的行。

主表(父表):對於兩個具有關聯關系的表而言,相關聯字段中主鍵所在的那個表即是主表;

從表(子表):對於兩個具有關聯關系的表而言,相關聯字段中外鍵所在的那個表即是從表。

被指向的實體,稱之為主實體(主表),也叫父實體(父表)

負責指向的實體,稱之為從實體(從表),也叫子實體(子表);

外鍵.jpg

若‘表1’的一個列既是主鍵又是外鍵,而這個外鍵約束又對應另一個表‘表2’的主鍵,那么‘表1’和‘表2’就可以合並起來了

2.作用:

外鍵的主要作用是保持數據的一致性、完整性。

如果主表沒有相關的記錄,從表不能插入;

更新時,不能改為主鍵表中沒有的值;

刪除主鍵表記錄時,可以在建外鍵時選定外鍵記錄一起級聯刪除還是拒絕刪除;同樣有級聯更新和拒絕更新的選擇。

ON DELETE CASCADE 級聯刪除

ON UPDATE CASCADE 級聯更新

3.設置MySQL外鍵約束字段的規則:

Ø 父表必須已經存在於數據庫中,或者是當前正在創建的表;若是后者,則父表與子表是同一個表,這樣的表稱為自參照完整性。

Ø 必須為父鍵定義主鍵。

Ø 主鍵不能包含空值,但允許在外鍵中出現空值;也就是說,只要外鍵的每個非空值出現在指定的主鍵中,這個外鍵的內容就是正確的。

Ø 在父表的表名后面指定列名或列名的組合,這個列的組合必須是父鍵的主鍵或者候選鍵。

Ø 外鍵中列的數據類型和父鍵主鍵中對應的數據類型相同。

Ø 外鍵中列的數目必須和父鍵中列的數目相同。

4.創建、添加外鍵的語法規則:

(1) 創建
[CONSTRAINT <外鍵名>] FOREIGN KEY 字段名 [,字段名2,…]

REFERENCES <主表名> 主鍵列1 [,主鍵列2,…]

“外鍵名”為定義的外鍵約束的名稱,一個表中不能有相同名稱的外鍵;

“字段名”表示子表需要添加外鍵約束的字段列;

“主表名”即被子表外鍵所依賴的表的名稱;

“主鍵列”表示主表中定義的主鍵列,或者列組合。

(2) 添加
ALTER TABLE <數據表名> ADD CONSTRAINT <外鍵名> (形如:FK_從表_主表)

FOREIGN KEY (<列名>) REFERENCES <主表名> (<列名>);

實例1:在test_db數據庫中創建employee表和dept表,表結構如下:

Employee表結構

字段名 字段說明 數據類型 主鍵 外鍵 非空 唯一 自增
e_no 員工編號 INT(11)
e_name 員工姓名 VARCHAR(50)
e_gender 員工性別 CHAR(2)
dept_no 部門編號 INT(11)
e_job 職位 VARCHAR(50)
e_salary 薪水 INT(11)
hiredate 入職日期 DATE

Dept表結構

字段名 字段說明 數據類型 主鍵 外鍵 非空 唯一 自增
d_no 部門編號 INT(11)
d_name 部門名稱 VARCHAR(50)
d_location 部門地址 VARCHAR(100)

創建數據表dept的SQL語句:

mysql> create table dept
  -> (
  -> d_no int(11) primary key not null unique auto_increment,
  -> d_name varchar(50) not null,
  -> d_location varchar(100)
  -> );
Query OK, 0 rows affected (0.01 sec)

創建數據表employee,並在表employee上創建外鍵約束,讓它的鍵dept_no作為外鍵關聯到表dept的主鍵d_no,SQL語句如下:

mysql> create table employee
  -> (
  -> e_no int(11) primary key not null unique,
  -> e_name varchar(5) not null,
  -> e_gender char(2),
  -> dept_no int (11) not null,
  -> e_job varchar(50) not null,
  -> e_salary int(11) not null,
  -> hireDate date not null,
  -> constraint fk_dept_employee
  -> foreign key(dept_no) references dept(d_no)
-> );
Query OK, 0 rows affected (0.01 sec)

以上語句執行之后,在表employee上添加了名稱為fk_dept_employee的外鍵約束,

外鍵名稱為dept_no,其依賴於表dept的主鍵d_no

#查看表結構:
mysql> show create table employee\G

*************************** 1. row ***************************
     Table: employee
Create Table: CREATE TABLE `employee` (
 `e_no` int(11) NOT NULL,
 `e_name` varchar(5) NOT NULL,
 `e_gender` char(2) DEFAULT NULL,
 `dept_no` int(11) NOT NULL,
 `e_job` varchar(50) NOT NULL,
 `e_salary` int(11) NOT NULL,
 `hireDate` date NOT NULL,
 PRIMARY KEY (`e_no`),
 UNIQUE KEY `e_no` (`e_no`),
 KEY `fk_dept_employee` (`dept_no`),
 CONSTRAINT `fk_dept_employee` FOREIGN KEY (`dept_no`) REFERENCES `dept` (`d_no
`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk
1 row in set (0.00 sec)
/*

關聯指的是在關系數據型數據庫中,相關表之間的聯系。它是通過相同的屬性或屬性組來表示的。子表的外鍵必須關聯父鍵的主鍵,且關鍵字段的數據類型必須匹配,如果類型不一樣,則創建子表時會出現錯誤” ERROR 1005 (HY000): Can't create table 'database.tablename' (errno: 150)”。

mysql> alter table employee
  -> add constraint fk_dept_employee
  -> foreign key(dept_no)
  -> references dept(d_no);
ERROR 1005 (HY000): Can't create table 'test_db.#sql-888_1' (errno: 150)
*/

實例2:在數據庫’test_db1’中創建數據表employee和dept,修改數據表 employee,將字段dept_no設置為外鍵,與數據表dept的主鍵d_no進行關聯,SQL語句如下;

mysql> create table employee
  -> (
  -> e_no int(11) primary key not null unique,
  -> e_name varchar(50) not null,
  -> e_gender char(2),
  -> dept_no int(11) not null,
  -> e_job varchar(50) not null,
  -> e_salary int(11) not null,
  -> hiredate date not null
  -> );
Query OK, 0 rows affected (0.01 sec)

mysql> create table dept
  -> (
  -> d_no int(11) primary key  not null unique auto_increment,
  -> d_name varchar(50) not null,
  -> d_location varchar(100)
  -> );
Query OK, 0 rows affected (0.01 sec)

#添加外鍵約束:

mysql> alter table employee
  -> add constraint fk_dept_employee
  -> foreign key(dept_no)
  -> references dept(d_no);
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

#查看表結構:

mysql> show create table employee\G
*************************** 1. row ***************************
    Table: employee
Create Table: CREATE TABLE `employee` (
 `e_no` int(11) NOT NULL,
 `e_name` varchar(50) NOT NULL,
 `e_gender` char(2) DEFAULT NULL,
 `dept_no` int(11) NOT NULL,
 `e_job` varchar(50) NOT NULL,
 `e_salary` int(11) NOT NULL,
 `hiredate` date NOT NULL,
 PRIMARY KEY (`e_no`),
 UNIQUE KEY `e_no` (`e_no`),
 KEY `fk_dept_employee` (`dept_no`),
 CONSTRAINT `fk_dept_employee` FOREIGN KEY (`dept_no`) REFERENCES `dept` (`d_no
`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk
1 row in set (0.00 sec)

5.刪除外鍵:

ALTER TABLE <表名> DROP FOREIGN KEY <外鍵約束名>;

(外鍵一旦刪除,就會解除主表和從表間的關聯關系)

mysql> alter table employee drop foreign key fk_dept_employee;
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show create table employee\G;
*************************** 1. row ***************************
    Table: employee
Create Table: CREATE TABLE `employee` (
 `e_no` int(11) NOT NULL,
 `e_name` varchar(5) NOT NULL,
 `e_gender` char(2) DEFAULT NULL,
 `dept_no` int(11) NOT NULL,
 `e_job` varchar(50) NOT NULL,
 `e_salary` int(11) NOT NULL,
 `hireDate` date NOT NULL,
 PRIMARY KEY (`e_no`),
 UNIQUE KEY `e_no` (`e_no`),
 KEY `fk_dept_employee` (`dept_no`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk
1 row in set (0.00 sec)

6.外鍵約束的三種形式:

(1) district:嚴格模式(默認),父表不能刪除或更新一個已經被子表數據引用的記錄。

mysql> delete from departments where d_no=1;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constrai
nt fails (`yggl`.`employee`, CONSTRAINT `fk_dept_emp` FOREIGN KEY (`dept_no`) RE
FERENCES `departments` (`d_no`))

(2) cascade:級聯模式,父鍵的操作,對應子表關聯的數據也跟着操作。

(3) set null:置空模式,父表被操作之后,子表對應的外鍵字段被置空。

通常情況下,合理的模式應該是這樣:刪除父表中的數據,子表置空;更新父表的時候,子表做級聯操作。(foreign key(外鍵字段) references 父鍵(外鍵字段) on delete set null on update cascade)

指定模式的語法:

foreign key(外鍵字段) references 父表(外鍵字段) on delete 模式 on update 模式


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM