外鍵約束(foreign key
)就是表與表之間的某種約定的關係,因爲這種關係的存在,咱們可以讓表與表之間的數據,更加的完整,關連性更強。數據庫
關於數據表的完整性和關連性,能夠舉個例子測試
有二張表,一張是用戶表,一張是訂單表:code
1.若是我刪除了用戶表裏的用戶,那麼訂單表裏面跟這個用戶有關的數據,就成了無頭數據了,不完整了。 2.若是我在訂單表裏面,隨便插入了一條數據,這個訂單在用戶表裏面,沒有與之對應的用戶。這樣數據也不完整了。
若是有外鍵的話,就方便多了,能夠不讓用戶刪除數據,或者刪除用戶的話,經過外鍵一樣刪除訂單表裏面的數據,這樣也能讓數據完整。索引
經過外鍵約束,每次插入或更新數據表時,都會檢查數據的完整性。ci
語法:unicode
create table 數據表名稱( ..., [CONSTRAINT [約束名稱]] FOREIGN KEY [外鍵字段] REFERENCES [外鍵表名](外鍵字段,外鍵字段2…..) [ON DELETE CASCADE ] [ON UPDATE CASCADE ] )
參數的解釋:rem
RESTRICT: 拒絕對父表的刪除或更新操做。 CASCADE: 從父表刪除或更新且自動刪除或更新子表中匹配的行。ON DELETE CASCADE和ON UPDATE CASCADE均可用
注意:on update cascade是級聯更新的意思,on delete cascade是級聯刪除的意思,意思就是說當你更新或刪除主鍵表,那外鍵表也會跟隨一塊兒更新或刪除。io
精簡化後的語法:innodb
foreign key 當前表的字段 references 外部表名 (關聯的字段) type=innodb
例子:咱們建立一個數據庫,包含用戶信息表和訂單表table
MariaDB [book]> create database market; # 建立market數據庫 Query OK, 1 row affected (0.00 sec) MariaDB [book]> use market; # 使用market數據庫 Database changed MariaDB [market]> create table userprofile(id int(11) not null auto_increment, name varchar(50) not null default '', sex int(1) not null default '0', primary key(id))ENGINE=innodb; # 建立userprofile數據表,指定使用innodb引擎 Query OK, 0 rows affected (0.07 sec) MariaDB [market]> create table user_order(o_id int(11) auto_increment, u_id int(11) default '0', username varchar(50), money int(11), primary key(o_id), index(u_id), foreign key order_f_key(u_id) references userprofile(id) on delete cascade on update cascade); # 建立user_order數據表,同時爲user_order表的u_id字段作外鍵約束,綁定userprofile表的id字段 Query OK, 0 rows affected (0.04 sec) MariaDB [market]> insert into userprofile(name,sex)values('HA',1),('LB',2),('HPC',1); # 向userprofile數據表插入三條記錄 Query OK, 3 rows affected (0.01 sec) Records: 3 Duplicates: 0 Warnings: 0 MariaDB [market]> select * from userprofile; # 查詢userprofile數據表的全部記錄 +----+------+-----+ | id | name | sex | +----+------+-----+ | 1 | HA | 1 | | 2 | LB | 2 | | 3 | HPC | 1 | +----+------+-----+ 3 rows in set (0.00 sec) MariaDB [market]> insert into user_order(u_id,username,money)values(1,'HA',234),(2,'LB',146),(3,'HPC',256); # 向user_order數據表插入三條記錄 Query OK, 3 rows affected (0.02 sec) Records: 3 Duplicates: 0 Warnings: 0 MariaDB [market]> select * from user_order; # 查詢user_order數據表的全部記錄 +------+------+----------+-------+ | o_id | u_id | username | money | +------+------+----------+-------+ | 1 | 1 | HA | 234 | | 2 | 2 | LB | 146 | | 3 | 3 | HPC | 256 | +------+------+----------+-------+ 3 rows in set (0.00 sec) MariaDB [market]> select id,name,sex,money,o_id from userprofile,user_order where id=u_id; # 聯表查詢 +----+------+-----+-------+------+ | id | name | sex | money | o_id | +----+------+-----+-------+------+ | 1 | HA | 1 | 234 | 1 | | 2 | LB | 2 | 146 | 2 | | 3 | HPC | 1 | 256 | 3 | +----+------+-----+-------+------+ 3 rows in set (0.03 sec)
MariaDB [market]> delete from userprofile where id=1; # 刪除user表中id爲1的數據 Query OK, 1 row affected (0.01 sec) MariaDB [market]> select id,name,sex,money,o_id from userprofile,user_order where id=u_id; +----+------+-----+-------+------+ | id | name | sex | money | o_id | +----+------+-----+-------+------+ | 2 | LB | 2 | 146 | 2 | | 3 | HPC | 1 | 256 | 3 | +----+------+-----+-------+------+ 2 rows in set (0.00 sec) MariaDB [market]> select * from user_order; # 查看order表的數據 +------+------+----------+-------+ | o_id | u_id | username | money | +------+------+----------+-------+ | 2 | 2 | LB | 146 | | 3 | 3 | HPC | 256 | +------+------+----------+-------+ 3 rows in set (0.00 sec)
更新數據以前的狀態
MariaDB [market]> select * from userprofile; # 查看userprofile表的數據 +----+------+-----+ | id | name | sex | +----+------+-----+ | 2 | LB | 2 | | 3 | HPC | 1 | +----+------+-----+ 3 rows in set (0.00 sec) MariaDB [market]> select * from user_order; # 查看order表的數據 +------+------+----------+-------+ | o_id | u_id | username | money | +------+------+----------+-------+ | 2 | 2 | LB | 146 | | 3 | 3 | HPC | 256 | +------+------+----------+-------+ 3 rows in set (0.00 sec)
更新數據
MariaDB [market]> update userprofile set id=6 where id=2; # 把userprofile數據表中id爲2的用戶改成id爲6 Query OK, 1 row affected (0.02 sec) Rows matched: 1 Changed: 1 Warnings: 0
更新數據後的狀態
MariaDB [market]> select id,name,sex,money,o_id from userprofile,user_order where id=u_id; # 聯表查詢,能夠看出表中已經沒有id爲2的用戶了 +----+------+-----+-------+------+ | id | name | sex | money | o_id | +----+------+-----+-------+------+ | 6 | LB | 2 | 146 | 2 | | 3 | HPC | 1 | 256 | 3 | +----+------+-----+-------+------+ 2 rows in set (0.00 sec) MariaDB [market]> select * from userprofile; # 查看userprofile表的數據,id只剩下3和6 +----+------+-----+ | id | name | sex | +----+------+-----+ | 3 | HPC | 1 | | 6 | LB | 2 | +----+------+-----+ 2 rows in set (0.00 sec) MariaDB [market]> select * from user_order; # 查看user_order表的數據,u_id也改成6 +------+------+----------+-------+ | o_id | u_id | username | money | +------+------+----------+-------+ | 2 | 6 | LB | 146 | | 3 | 3 | HPC | 256 | +------+------+----------+-------+ 2 rows in set (0.00 sec)
MariaDB [market]> insert into user_order(u_id,username,money)values(5,"XJ",345); # 單獨向user_order數據表中插入數據,插入數據失敗 ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`market`.`user_order`, CONSTRAINT `user_order_ibfk_1` FOREIGN KEY (`u_id`) REFERENCES `userprofile` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)
在上面的例子中,user_order表的外鍵約束,user_order表受userprofile表的約束
在user_order
裏面插入一條數據u_id爲5用戶,在userprofile表裏面根本沒有,因此插入數據失敗
先向userprofile表中插入記錄,再向user_order
表中插入記錄就能夠了
MariaDB [market]> insert into userprofile values(5,"XJ",1); # 先向userprofile數據表中插入id爲5的記錄,插入數據成功 Query OK, 1 row affected (0.01 sec) MariaDB [market]> insert into user_order(u_id,username,money) values(5,"XJ",345); # 再向user_order數據表中插入數據,成功 Query OK, 1 row affected (0.00 sec) MariaDB [market]> select * from userprofile; # 查詢userprofile數據表中的全部記錄 +----+------+-----+ | id | name | sex | +----+------+-----+ | 3 | HPC | 1 | | 5 | XJ | 1 | | 6 | LB | 2 | +----+------+-----+ 3 rows in set (0.00 sec) MariaDB [market]> select * from user_order; # 查詢user_order數據表中的全部記錄 +------+------+----------+-------+ | o_id | u_id | username | money | +------+------+----------+-------+ | 2 | 6 | LB | 146 | | 3 | 3 | HPC | 256 | | 5 | 5 | XJ | 345 | +------+------+----------+-------+ 3 rows in set (0.01 sec)
語法:
alter table 數據表名稱 add [constraint [約束名稱] ] foreign key (外鍵字段,..) references 數據表(參照字段,...) [on update cascade|set null|no action] [on delete cascade|set null|no action] )
例子:
MariaDB [market]> create table user_order1(o_id int(11) auto_increment,u_id int(11) default "0",username varchar(50),money int(11),primary key(o_id),index(u_id)); # 建立user_order1數據表,建立表時不使用外鍵約束 Query OK, 0 rows affected (0.11 sec) MariaDB [market]> show create table user_order1; # 查看user_order1數據表的建立信息,沒有外鍵約束 +-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | user_order1 | CREATE TABLE `user_order1` ( `o_id` int(11) NOT NULL AUTO_INCREMENT, `u_id` int(11) DEFAULT '0', `username` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL, `money` int(11) DEFAULT NULL, PRIMARY KEY (`o_id`), KEY `u_id` (`u_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci | +-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.01 sec) MariaDB [market]> alter table user_order1 add foreign key(u_id) references userprofile(id) on delete cascade on update cascade; # 使用alter修改user_order1數據表,爲user_order1數據表添加外鍵約束 Query OK, 0 rows affected (0.05 sec) Records: 0 Duplicates: 0 Warnings: 0 MariaDB [market]> show create table user_order1; # 查看user_order1數據表的建立信息,已經添加了外鍵約束 +-------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | user_order1 | CREATE TABLE `user_order1` ( `o_id` int(11) NOT NULL AUTO_INCREMENT, `u_id` int(11) DEFAULT '0', `username` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL, `money` int(11) DEFAULT NULL, PRIMARY KEY (`o_id`), KEY `u_id` (`u_id`), CONSTRAINT `user_order1_ibfk_1` FOREIGN KEY (`u_id`) REFERENCES `userprofile` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci | +-------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
語法
alter table 數據表名稱 drop foreign key 約束(外鍵)名稱
例子:
MariaDB [market]> show create table user_order1; # 查看user_order1數據表的建立信息,包含外鍵約束 +-------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | user_order1 | CREATE TABLE `user_order1` ( `o_id` int(11) NOT NULL AUTO_INCREMENT, `u_id` int(11) DEFAULT '0', `username` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL, `money` int(11) DEFAULT NULL, PRIMARY KEY (`o_id`), KEY `u_id` (`u_id`), CONSTRAINT `user_order1_ibfk_1` FOREIGN KEY (`u_id`) REFERENCES `userprofile` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci | +-------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) MariaDB [market]> alter table user_order1 drop foreign key user_order1_ibfk_1; # 爲user_order1數據表刪除外鍵約束,外鍵名稱必須與從`show create table user_order1`語句中查到的相同 Query OK, 0 rows affected (0.05 sec) Records: 0 Duplicates: 0 Warnings: 0 MariaDB [market]> show create table user_order1; # 查看user_order1數據表的建立信息,外鍵約束已經被刪除了 +-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | user_order1 | CREATE TABLE `user_order1` ( `o_id` int(11) NOT NULL AUTO_INCREMENT, `u_id` int(11) DEFAULT '0', `username` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL, `money` int(11) DEFAULT NULL, PRIMARY KEY (`o_id`), KEY `u_id` (`u_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci | +-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
要想外鍵建立成功,必須知足如下4個條件:
一、確保參照的表和字段存在。 二、組成外鍵的字段被索引。 三、必須使用type指定存儲引擎爲:innodb. 四、外鍵字段和關聯字段,數據類型必須一致。
1.on delete cascade on update cascade 添加級聯刪除和更新: 2.確保參照的表userprofile中id字段存在。 3.確保組成外鍵的字段u_id被索引 4.必須使用type指定存儲引擎爲:innodb。 5.外鍵字段和關聯字段,數據類型必須一致。