一,什麼是foreign key,及其完整性html
我的以爲,foreign key就是表與表之間的某種約定的關係,因爲這種關係的存在,咱們可以讓表與表之間的數據,更加的完整,關連性更強。關於完整性,關連性我舉個例子,你們就會明白了。mysql
有二張表,一張是用戶表,一張是訂單表:sql
1,若是我刪除了用戶表裏的用戶,那麼訂單表裏面根這個用戶有關的數據,就成了無頭數據了,不完整了。數據庫
2,若是我在訂單表裏面,隨便插入了一條數據,這個訂單在用戶表裏面,沒有與之對應的用戶。這樣數據也不完整了。post
若是有外鍵的話,就方便多了,能夠不讓用戶刪除數據,或者刪除用戶的話,經過外鍵一樣刪除訂單表裏面的數據,這樣也能讓數據完整。spa
二,使用foreign key,遵照如下幾點規則code
1,有外鍵約束的表,必須是innodb型htm
2,外鍵約束的二個表,原本就相關係的表,而且要有索引關係,若是沒有,建立外鍵時也能夠建立索引。blog
3,不支持對外鍵列的索引前綴。這樣的後果之一是BLOB和TEXT列不被包括在一個外鍵中,這是由於對這些列的索引必須老是包含一個前綴長度。索引
4,mysql外鍵的名子在數據庫內要是惟一的
三,建立foreign key的語法規則
[CONSTRAINT symbol] FOREIGN KEY [id] (index_col_name, ...) REFERENCES tbl_name (index_col_name, ...) [ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION}] [ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION}]
四,外鍵維護數據完整性的5種方式
1,CASCADE: 從父表刪除或更新且自動刪除或更新子表中匹配的行。ON DELETE CASCADE和ON UPDATE CASCADE均可用。在兩個表之間,你不該定義若干在父表或子表中的同一列採起動做的ON UPDATE CASCADE子句。
2,SET NULL: 從父表刪除或更新行,並設置子表中的外鍵列爲NULL。若是外鍵列沒有指定NOT NULL限定詞,這就是惟一合法的。ON DELETE SET NULL和ON UPDATE SET NULL子句被支持。
3,NO ACTION: 在ANSI SQL-92標準中,NO ACTION意味這不採起動做,就是若是有一個相關的外鍵值在被參考的表裏,刪除或更新主要鍵值的企圖不被容許進行(Gruber, 掌握SQL, 2000:181)。 InnoDB拒絕對父表的刪除或更新操做。
4,RESTRICT: 拒絕對父表的刪除或更新操做。NO ACTION和RESTRICT都同樣,刪除ON DELETE或ON UPDATE子句。(一些數據庫系統有延期檢查,而且NO ACTION是一個延期檢查。在MySQL中,外鍵約束是被當即檢查的,因此NO ACTION和RESTRICT是一樣的)。
5,SET DEFAULT: 這個動做被解析程序識別,但InnoDB拒絕包含ON DELETE SET DEFAULT或ON UPDATE SET DEFAULT子句的表定義。
五,實例說明foreign key的用法
- mysql> CREATE TABLE `user` ( //建立用戶表
- -> `id` int(11) NOT NULL auto_increment COMMENT '用戶ID',
- -> `name` varchar(50) NOT NULL default '' COMMENT '名稱',
- -> `sex` int(1) NOT NULL default '0' COMMENT '0爲男,1爲女',
- -> PRIMARY KEY (`id`)
- -> ) ENGINE=innodb DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; //innodb引擎
- Query OK, 0 rows affected, 1 warning (0.11 sec)
- mysql> insert into user (name,sex)values("tank",1),("zhang",2); //插入二條數據
- Query OK, 2 rows affected (0.00 sec)
- Records: 2 Duplicates: 0 Warnings: 0
- mysql> create table `order` ( //建立訂單表
- -> `order_id` int(11) not null auto_increment comment '訂單ID',
- -> `u_id` int(11) not null default '0' comment '用戶ID',
- -> `username` varchar(50) not null default '' comment '用戶名',
- -> `money` int(11) not null default '0' comment '錢數',
- -> `datetime` timestamp not null default current_timestamp comment '生成時
- 間',
- -> primary key(`order_id`),
- -> index (`u_id`),
- -> FOREIGN KEY order_f_key (u_id) REFERENCES user(id) //建立外鍵
- -> )ENGINE=innodb DEFAULT CHARSET=utf8 AUTO_INCREMENT=1; //innodb引擎
- Query OK, 0 rows affected, 1 warning (0.06 sec)
- mysql> INSERT INTO `order` (`u_id`, `username`, `money`, `datetime`) VALUES ('1', 'tank','2222',
- CURRENT_TIMESTAMP); //插入一條訂單
- Query OK, 1 row affected (0.00 sec)
- mysql> delete from user where id =1; //刪除用戶1,不給刪除,由於order表裏面有和這條數據有關連的數據
- ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test/order`, CONSTRAINT `order_ibfk_1` FOREIGN KEY (`u_id`) REFERENCES `user` (`id`))
- //下面在order裏面插入一條數據u_id爲5用戶,在user表裏面根本沒有,因此插入不進去。
- mysql> INSERT INTO `order` (`u_id`, `username`, `money`, `datetime`) VALUES ('5', 'good','123', CURRENT_TIMESTAMP);
- ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test/order`, CONSTRAINT `order_ibfk_1` FOREIGN KEY (`u_id`) REFERENCES `user` (`id`))
- //把u_id改爲2就能夠插進去了,由於user表裏面有id=2的用戶
- mysql> INSERT INTO `order` (`u_id`, `username`, `money`, `datetime`) VALUES ('2', 'zhang','3452', CURRENT_TIMESTAMP);
- Query OK, 1 row affected (0.00 sec)
- mysql> show create table `order`\G; //查看建立表的數據,爲的是查看foreign key的名子,還有order二邊要有`這個符號
- *************************** 1. row ***************************
- Table: order
- Create Table: CREATE TABLE `order` (
- `order_id` int(11) NOT NULL auto_increment COMMENT '訂單ID',
- `u_id` int(11) NOT NULL default '0' COMMENT '用戶ID',
- `username` varchar(50) NOT NULL default '' COMMENT '用戶名',
- `money` int(11) NOT NULL default '0' COMMENT '錢數',
- `datetime` timestamp NOT NULL default CURRENT_TIMESTAMP COMMENT '生成時間',
- PRIMARY KEY (`order_id`),
- KEY `u_id` (`u_id`),
- CONSTRAINT `order_ibfk_1` FOREIGN KEY (`u_id`) REFERENCES `user` (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
- 1 row in set (0.00 sec)
- ERROR:
- No query specified
- mysql> alter table `order` drop foreign key order_ibfk_1; //刪除foreign key,mysql裏面沒有修改foreign key的命令
- Query OK, 2 rows affected (0.10 sec)
- Records: 2 Duplicates: 0 Warnings: 0
- //刪除後在新增
- mysql> alter table `order` add foreign key(u_id) references user(id) on delete cascade on update cascade;
- Query OK, 2 rows affected (0.00 sec)
- Records: 2 Duplicates: 0 Warnings: 0
- mysql> update user set id=6 where id=1; //更新user表裏面的id
- Query OK, 1 row affected (0.05 sec)
- Rows matched: 1 Changed: 1 Warnings: 0
- mysql> select * from `order` where u_id=6; //order表裏面的數據,也根着改變了。
- +----------+------+----------+-------+---------------------+
- | order_id | u_id | username | money | datetime |
- +----------+------+----------+-------+---------------------+
- | 2 | 6 | tank | 2222 | 2010-11-25 22:18:57 |
- +----------+------+----------+-------+---------------------+
- 1 row in set (0.00 sec)
foreign key只能用於innodb,而且對數據進行操做時,會對外鍵關聯的表進行檢索,會影響效率的。因此對外鍵的使用,要根據我的的實際狀況。
做者:海底蒼鷹地址:http://blog.51yip.com/mysql/1136.html