1. 程式人生 > >MySQL基礎之 主鍵外鍵設置

MySQL基礎之 主鍵外鍵設置

cit eight warn unsigned sql delet 行操作 名稱 style

外鍵:

定義:如果表A的主關鍵字是表B中的字段,則該字段稱為表B的外鍵,表A稱為主表,表B稱為從表。

作用:外鍵是用來實現參照完整性的,不同的外鍵約束方式將可以是兩張表緊密的結合起來。比如修改或者刪除的級聯操作等,外鍵主要用來保證數據的完整性和一致性。

條件:

  1、創建外鍵的兩個表,父表與子表必須是InnoDB存儲引擎。

  2、創建外鍵的時候,父表要創建索引,一般為主鍵索引。子表在創建外鍵的時候也必須要創建索引。

  3、子表的外鍵必須和父表的主鍵數據類型相對應(字段的類型和值必須一樣或者相似,比如int也可以對應tinyint)。

語法:

下面這個是在子表中操作的:

[CONSTRAINT  Symbol
] FOREIGN KEY [id] (index_col_name,.....) REFERENCES tbl_name (index_col_name,...) [ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}] [ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]

其中Symbol僅僅是給約束自定義一個名稱,方便以後我們刪除約束。

  RESTRICT和NO ACTION相同,是指限制在子表有關聯記錄的情況下父表不能進行操作。比如:DELETE RESTRICT表示主表在刪除記錄的時候,如果子表有對應的記錄,則不允許刪除。比如UPDATE CASCADE表示主表在更新記錄的時候,如果子表有對應的記錄,則子表也更新。(其實更新的就是主鍵和外鍵的那一列的值)。

  CASCADE:表示父表在更新或者刪除時,也更新或者刪除子表對應的記錄。

  SET NULL:表示父表的更新或者刪除的時候,那麽子表對應的字段被會SET NULL。

註意:當某個表被其他表創建了外鍵參照,那麽該表的對應索引或者主鍵禁止被刪除。

例子:

首先是我們創建兩個表,一個是父表,一個是字表。字表設置有參照約束。

mysql> create table country( 
    -> country_id smallint unsigned not null auto_increment,
    -> country varchar(50) not null
, -> last_update timestamp not null default current_timestamp on update current_timestamp, -> primary key(country_id) -> )engine=InnoDB default charset=utf8; Query OK, 0 rows affected (0.10 sec) mysql> desc country; +-------------+----------------------+------+-----+-------------------+-----------------------------+ | Field | Type | Null | Key | Default | Extra | +-------------+----------------------+------+-----+-------------------+-----------------------------+ | country_id | smallint(5) unsigned | NO | PRI | NULL | auto_increment | | country | varchar(50) | NO | | NULL | | | last_update | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | +-------------+----------------------+------+-----+-------------------+-----------------------------+ 3 rows in set (0.00 sec) mysql> create table city( -> city_id smallint unsigned not null auto_increment, -> city varchar(50) not null, -> country_id smallint unsigned not null, -> last_update timestamp not null default current_timestamp on update current_timestamp, -> primary key(city_id), -> key idx_fk_country_id(country_id), -> constraint fk_city_country foreign key(country_id) references country(country_id) on delete restrict on update cascade -> )engine=InnoDB default charset=utf8; Query OK, 0 rows affected (0.04 sec) mysql> desc country; +-------------+----------------------+------+-----+-------------------+-----------------------------+ | Field | Type | Null | Key | Default | Extra | +-------------+----------------------+------+-----+-------------------+-----------------------------+ | country_id | smallint(5) unsigned | NO | PRI | NULL | auto_increment | | country | varchar(50) | NO | | NULL | | | last_update | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | +-------------+----------------------+------+-----+-------------------+-----------------------------+ 3 rows in set (0.00 sec) mysql> insert into country values(1,‘English‘,now()); Query OK, 1 row affected (0.00 sec) mysql> select * from country; +------------+---------+---------------------+ | country_id | country | last_update | +------------+---------+---------------------+ | 1 | English | 2018-10-25 10:34:49 | +------------+---------+---------------------+ 1 row in set (0.00 sec) mysql> desc city; +-------------+----------------------+------+-----+-------------------+-----------------------------+ | Field | Type | Null | Key | Default | Extra | +-------------+----------------------+------+-----+-------------------+-----------------------------+ | city_id | smallint(5) unsigned | NO | PRI | NULL | auto_increment | | city | varchar(50) | NO | | NULL | | | country_id | smallint(5) unsigned | NO | MUL | NULL | | | last_update | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | +-------------+----------------------+------+-----+-------------------+-----------------------------+ 4 rows in set (0.00 sec) mysql> insert into city values(251,Kabul,1,now()); Query OK, 1 row affected (0.00 sec) mysql> select * from city; +---------+-------+------------+---------------------+ | city_id | city | country_id | last_update | +---------+-------+------------+---------------------+ | 251 | Kabul | 1 | 2018-10-25 10:36:51 | +---------+-------+------------+---------------------+ 1 row in set (0.00 sec)

  上面的“on update current_timestamp”表示更新表的記錄的時候 ,也自動更新修改的時間。一句話“在創建新記錄和修改現有記錄的時候都對這個數據列刷新”。

1、現在我們刪除父表中的一個數據記錄。

mysql> delete from country where country_id=1;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`exercise`.`city`, CONSTRAINT `fk_city_country` FOREIGN KEY (`country_id`) REFERENCES `country` (`country_id`) ON UPDATE CASCADE)

我們發現是刪除不了的,因為字表參照了父表的一個記錄(我們在字表參照裏面設置了“限制在字表有關聯的情況下父表不能刪除”---delete restrict)

2、然後我們更新一個記錄看看。

mysql> update country  set country_id=251 where country=English;  
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
mysql> SET SQL_SAFE_UPDATES=0;   #我是以安全模式啟動的mysql,設置一下就可以了
Query OK, 0 rows affected (0.00 sec)

mysql> update country  set country_id=251 where country=English;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from country;
+------------+---------+---------------------+
| country_id | country | last_update         |
+------------+---------+---------------------+
|        251 | English | 2018-10-25 10:47:01 |
+------------+---------+---------------------+
1 row in set (0.00 sec)

mysql> select * from city;      
+---------+-------+------------+---------------------+
| city_id | city  | country_id | last_update         |
+---------+-------+------------+---------------------+
|     251 | Kabul |        251 | 2018-10-25 10:38:28 |
+---------+-------+------------+---------------------+
1 row in set (0.00 sec)

我們更新的父表的主鍵記錄,發現子表的外鍵記錄也自動更新了,因為子表的外鍵參照父表的主鍵。並且子表在約束條件裏面寫了"update cascade"。

3、現在我們刪除父表的主鍵

mysql> alter table country drop column country_id;
ERROR 1829 (HY000): Cannot drop column country_id: needed in a foreign key constraint fk_city_country of table exercise.city

當某個表被其他表創建了外鍵參照,那麽該表的對應索引或者主鍵禁止被刪除。

還有一些需要註意的:

在導入多個表的數據的時候,如果需要忽略表之前的導入順序,可以暫時關閉外鍵的檢查,在執行load data和alter table操作的時候,可以暫時關閉外鍵約束來加快處理的速度。關閉的指令是“SET FORENGN_KEY_CHECKS=0”;執行完成之後,通過執行"SET FOREIGN_KEY_CHECKS=1"語句改回原始狀態。

MySQL基礎之 主鍵外鍵設置