132 MySQL表的完整性約束

1、表的完整性約束目的

  • 爲了防止不符合規範的數據進入數據庫,在用戶對數據進行插入、修改、刪除等操做時,DBMS自動按照必定的約束條件對數據進行監測,使不符合規範的數據不能進入數據庫,以確保數據庫中存儲的數據正確、有效、相容。python

  • 約束條件與數據類型的寬度同樣,都是可選參數,主要分爲如下幾種:
    • not null : 非空約束,指定某列不能爲空
    • auto_increment : 自增約束,只用在int型
    • unique : 字段惟一性約束,指定某列或幾列的數據不能重複
    • primary key : 主鍵,指定該列的值能夠惟一地標識該列記錄
    • forrign key : 外鍵,指定該行記錄從屬於主表中的一條記錄,主要用於參照完整性

2、not null

是否可空,null表示空,非字符串mysql

not null - 不可空linux

null - 可空nginx

2.1 not null 實例

1.建立t12表 id字段約束不爲空
mysql> create table t12 (id int not null);
Query OK, 0 rows affected (0.02 sec)

2.查看t12表中全部字段記錄
mysql> select * from t12;
Empty set (0.00 sec)

3.顯示t12表的結構
mysql> desc t12;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | NO   |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
row in set (0.00 sec)

4.不能向id列插入空元素,插入的是空值
mysql> insert into t12 values (null);
ERROR 1048 (23000): Column 'id' cannot be null

5.向t12表中插入正確數據
mysql> insert into t12 values (1);
Query OK, 1 row affected (0.01 sec)

2.2 default

咱們約束了某一列不爲空,若是這一列中常常有重複的內容,就須要咱們頻繁的插入,這樣會給咱們的操做帶來新的負擔,因而就出現了默認值的概念。c++

默認值,建立列時能夠指定默認值,當插入數據時若是未主動設置,則自動添加默認值。程序員

2.3 not null + default實例

1.建立t13表 id1字段約束不爲空,id2字段約束不爲空且默認值爲222
mysql> create table t13 (id1 int not null,id2 int not null default 222);
Query OK, 0 rows affected (0.01 sec)

2.顯示t13表結構
mysql> desc t13;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id1   | int(11) | NO   |     | NULL    |       |
| id2   | int(11) | NO   |     | 222     |       |
+-------+---------+------+-----+---------+-------+
rows in set (0.01 sec)

3.只向id1字段添加值,會發現id2字段會使用默認值填充
mysql> insert into t13 (id1) values (111);
Query OK, 1 row affected (0.00 sec)

4.顯示當前表的記錄
mysql> select * from t13;
+-----+-----+
| id1 | id2 |
+-----+-----+
| 111 | 222 |
+-----+-----+
row in set (0.00 sec)

5.id1字段不能爲空,因此不能單獨向id2字段填充值;
mysql> insert into t13 (id2) values (223);
ERROR 1364 (HY000): Field 'id1' doesn't have a default value

6.向id1,id2中分別填充數據,id2的填充數據會覆蓋默認值
mysql> insert into t13 (id1,id2) values (112,223);
Query OK, 1 row affected (0.00 sec)
mysql> select * from t13;
+-----+-----+
| id1 | id2 |
+-----+-----+
| 111 | 222 |
| 112 | 223 |
+-----+-----+
rows in set (0.00 sec)

2.4 not null 不生效

設置嚴格模式:
    不支持對not null字段插入null值
    不支持對自增加字段插入」值
    不支持text字段有默認值

直接在mysql中生效(重啓失效):
mysql>set sql_mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION";

配置文件添加(永久失效):
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

3、auto_increment(自增)

  • 設置字段的值在沒有被賦值時自增,只用於int型,而且字段必須設置爲鍵字段sql

  • 被約束的字段必須同時被key約束
  • 一個表只能由一個自增字段數據庫

3.1 實例

1.建立學生表不指定id,則自動增加
create table student(
id int unique auto_increment,
name varchar(20),
sex enum('male','female') default 'male'
);

mysql> desc student;
+-------+-----------------------+------+-----+---------+----------------+
| Field | Type                  | Null | Key | Default | Extra          |
+-------+-----------------------+------+-----+---------+----------------+
| id    | int(11)               | NO   | PRI | NULL    | auto_increment |
| name  | varchar(20)           | YES  |     | NULL    |                |
| sex   | enum('male','female') | YES  |     | male    |                |
+-------+-----------------------+------+-----+---------+----------------+
mysql> insert into student(name) values
    -> ('cecilia'),
    -> ('xichen')
    -> ;

mysql> select * from student;
+----+----------+------+
| id | name     | sex  |
+----+----------+------+
|  1 | cecilia  | male |
|  2 | xichen   | male |
+----+----------+------+


2. 也能夠指定id
mysql> insert into student values(4,'asb','female');
Query OK, 1 row affected (0.00 sec)

mysql> insert into student values(7,'wsb','female');
Query OK, 1 row affected (0.00 sec)

mysql> select * from student;
+----+---------+--------+
| id | name    | sex    |
+----+---------+--------+
|  1 | cecilia | male   |
|  2 | xichen  | male   |
|  4 | asb     | female |
|  7 | wsb     | female |
+----+---------+--------+


3. 對於自增的字段,在用delete刪除後,再插入值,該字段仍按照刪除前的位置繼續增加
mysql> delete from student;
Query OK, 4 rows affected (0.00 sec)

mysql> select * from student;
Empty set (0.00 sec)

mysql> insert into student(name) values('ysb');
mysql> select * from student;
+----+------+------+
| id | name | sex  |
+----+------+------+
|  8 | ysb  | male |
+----+------+------+

4. 應該用truncate清空表,比起delete一條一條地刪除記錄,truncate是直接清空表,在刪除大表時用它
mysql> truncate student;
Query OK, 0 rows affected (0.01 sec)

mysql> insert into student(name) values('xichen');
Query OK, 1 row affected (0.01 sec)

mysql> select * from student;
+----+--------+------+
| id | name   | sex  |
+----+--------+------+
|  1 | xichen | male |
+----+--------+------+
row in set (0.00 sec)

4、unique(惟一鍵)

惟一約束,指定某列或者幾列組合不能重複。架構

4.1 unique實例

方法一:
create table t1(
id int,
name varchar(20) unique,
course varchar(100)
);


方法二:
create table department2(
id int,
name varchar(20),
course varchar(100),
unique(name)
);


mysql> insert into t1 values(1,'xichen','計算機');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t1 values(1,'xichenT','計算機'); # 此時會報錯
ERROR 1062 (23000): Duplicate entry 'IT' for key 'name'

4.2 聯合惟一

  • ip在port不一樣時,能夠相同,ip不一樣時port也能夠相同,均合法
  • ip和port都相同時,就是重複數據,不合法
mysql>: create table tu1 (
    ip char(16), 
    port int, 
    unique(ip, port)# 聯合惟一
);
    

# 插入正確數據
mysql> insert into service values
    -> ('192.168.0.10',8080),
    -> ('192.168.0.20',8080),
    -> ('192.168.0.30',3306)
    -> ;
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0
            

# 插入重複數據 (ip,poor和已有的記錄重複了)
mysql> insert into service(name,host,port) values('192.168.0.10',8080);
ERROR 1062 (23000): Duplicate entry '192.168.0.10-8080' for key 'host'

5、primary key(主鍵)

  • 表都會擁有,不設置爲默認找第一個 不空,惟一 字段,未標識則建立隱藏字段
  • 主鍵爲了保證表中的每一條數據的該字段都是表格中的惟一值。換言之,它是用來獨一無二地確認一個表格中的每一行數據。
  • 主鍵能夠包含一個字段或多個字段。當主鍵包含多個欄位時,稱爲組合鍵 (Composite Key),也能夠叫聯合主鍵。
  • 主鍵能夠在建置新表格時設定 (運用 CREATE TABLE 語句),或是以改變現有的表格架構方式設定 (運用 ALTER TABLE)。
  • 主鍵必須惟一,主鍵值非空;能夠是單一字段,也能夠是多字段組合。

5.1 單字段作主鍵

#方法一:not null+unique
create table t1(
id int not null unique, #主鍵 默認找第一個設爲惟一鍵的字段
name varchar(20) not null unique,
course varchar(100)
);

mysql> desc t1;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(11)      | NO   | PRI | NULL    |       |
| name    | varchar(20)  | NO   | UNI | NULL    |       |
| course  | varchar(100) | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
rows in set (0.01 sec)


#方法二:在某一個字段後用primary key
create table t2(
id int primary key, #主鍵
name varchar(20),
course varchar(100)
);

mysql> desc t2;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(11)      | NO   | PRI | NULL    |       |
| name    | varchar(20)  | YES  |     | NULL    |       |
| course  | varchar(100) | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
rows in set (0.00 sec)

#方法三:在全部字段後單獨定義primary key
create table t3(
id int,
name varchar(20),
course varchar(100),
primary key(id); #字段id設爲主鍵

mysql> desc t3;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(11)      | NO   | PRI | NULL    |       |
| name    | varchar(20)  | YES  |     | NULL    |       |
| course | varchar(100) | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
rows in set (0.01 sec)

# 方法四:給已經建成的表添加主鍵約束
mysql> create table t4(
    -> id int,
    -> name varchar(20),
    -> course varchar(100));
Query OK, 0 rows affected (0.01 sec)

mysql> desc t4;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(11)      | YES  |     | NULL    |       |
| name    | varchar(20)  | YES  |     | NULL    |       |
| course  | varchar(100) | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
rows in set (0.01 sec)

# 給已經建成的表添加主鍵約束
mysql> alter table t4 modify id int primary key;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc t4;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(11)      | NO   | PRI | NULL    |       |
| name    | varchar(20)  | YES  |     | NULL    |       |
| course  | varchar(100) | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
rows in set (0.01 sec)

5.2 多字段作主鍵(主鍵惟一)

# 建立多字段作主鍵(ip,port)
create table t1(
ip varchar(15),
port char(5),
name varchar(10) not null,
primary key(ip,port)
);


mysql> desc service;
+--------------+-------------+------+-----+---------+-------+
| Field        | Type        | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| ip           | varchar(15) | NO   | PRI | NULL    |       |
| port         | char(5)     | NO   | PRI | NULL    |       |
| name         | varchar(10) | NO   |     | NULL    |       |
+--------------+-------------+------+-----+---------+-------+
rows in set (0.00 sec)

# 插入兩條數據
mysql> insert into t1 values
    -> ('172.16.45.10','3306','mysqld'),
    -> ('172.16.45.11','3306','mariadb')
    -> ;
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> insert into t1 values ('172.16.45.10','3306','nginx');
ERROR 1062 (23000): Duplicate entry '172.16.45.10-3306' for key 'PRIMARY'

5.3 主鍵和惟一鍵分析

1.x爲主鍵:沒有設置primary key時,第一個 惟一自增鍵,會自動提高爲主鍵
mysql>: create table t1 (x int unique auto_increment, y int unique);
    
2.y爲主鍵:沒有設置primary key時,第一個 惟一自增鍵,會自動提高爲主鍵
mysql>: create table t2 (x int unique, y int unique auto_increment);
    
3.x爲主鍵:設置了主鍵就是設置的,主鍵沒設置自增,那自增是能夠設置在惟一鍵上的
mysql>: create table t3 (x int primary key, y int unique auto_increment);
    
4.x爲主鍵:設置了主鍵就是設置的,主鍵設置了自增,自增字段只能有一個,因此惟一鍵不能再設置自增了
mysql>: create table t4 (x int primary key auto_increment, y int unique);
    
5.默認主鍵:沒有設置主鍵,也沒有 惟一自增鍵,那系統會默認添加一個 隱式主鍵(不可見)
mysql>: create table t5 (x int unique, y int unique);

6、foreign key(外鍵)

foreign key:指定該行記錄從屬於主表中的一條記錄,主要用於參照完整性

重點:外鍵自己能夠不惟一,可是關聯的字段必須是惟一的

6.1 語法

foreign 主表字段名 references 被關聯表名/從表名(字段名)

6.2 建立外鍵實例

6.2.1 一對一的表關係設置外鍵(foreign key)

假設咱們要描述全部做者,須要描述的屬性有:做者id號,姓名,聯繫方式,性別,做者詳細信息(詳細信息info,地址address)、因爲做者的詳細信息咱們須要重複的存儲信息,而咱們都知道詳細信息都很長咱們不可能那字段去存儲它

因此:咱們能夠定義另一個做者詳細信息表,而後讓做者基本信息表關聯做者詳細信息表,如何關聯即 foreign key

下面就是咱們利用外鍵來創建一對一的關聯表

做者表author的屬性:id,name,mobile,sex,age,detail_id

做者詳細信息表author_detail屬性:id,info,address

1、錯誤案例

# 1.建立表不成功,緣由是咱們建立外鍵foreign key時,要先建立被關聯的表(從表)author_detail
mysql> create table author(
    -> id int primary key auto_increment,
    ->     name varchar(64) not null,
    ->     mobile char(11) unique not null,
    ->     sex enum('男', '女') default '男',
    ->     age int default 0,
    ->     detail_id int  not null,
    ->     foreign key(detail_id) references author_detail(id)
    -> );
ERROR 1215 (HY000): Cannot add foreign key constraint

# 出錯案例
# 2.建立的被關聯表的字段沒有這隻惟一性約束
1.先建立被關聯的表(從表)author_drtail ,能夠建立成功
mysql> create table author_detail(
    -> id int ,
    ->     info varchar(256),
    ->     address varchar(256)
    -> );
Query OK, 0 rows affected (0.40 sec)
2.在建立關聯的表(主表)author
# 會建立不成功,由於所關聯表的字段沒有設置惟一性約束!
mysql> create table author(
    -> id int primary key auto_increment,
    ->     name varchar(64) not null,
    ->     mobile char(11) unique not null,
    ->     sex enum('男', '女') default '男',
    ->     age int default 0,
    ->     detail_id int unique not null,
    ->     foreign key(detail_id) references author_detail(id)
    -> );
ERROR 1215 (HY000): Cannot add foreign key constraint

2、正確案例

1.建立兩個關聯表(author)與被關聯表(author_detail)
1.先建立被關聯的表(從表)(author_detail),能夠建立成功
mysql> create table author_detail(
    -> id int primary key auto_increment,#被關聯表設置惟一約束,爲主鍵
    ->     info varchar(256),
    ->     address varchar(256)
    -> );
Query OK, 0 rows affected (0.43 sec)

2.再建立關聯表(主表)(author),能夠建立成功
mysql> create table author(
    -> id int primary key auto_increment,
    ->     name varchar(64) not null,
    ->     mobile char(11) unique not null,
    ->     sex enum('男', '女') default '男',
    ->     age int default 0,
    ->     detail_id int unique not null,# 外鍵字段,設了惟一性,由於是一對一的表關係
    ->     foreign key(detail_id) references author_detail(id)
    -> );
Query OK, 0 rows affected (0.63 sec)
2. 對兩個表進行數據插入
# 先插入關聯表(主表author)如數據出錯
1.插入數據,出現錯誤,要先插入被關聯表的數據
mysql>insert into author(name,mobile,detail_id) values('Tom','13344556677', 1);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`mydb`.`author`, CONSTRAINT `author_ibfk_1` FOREIGN KEY (`detail_id`) REFERENCES `author_detail` (`id`))

## 先插入被關聯(author_detail)的表的數據,不會出錯
1.給被關聯的從表(author_detail)插入數據
mysql>insert into author_detail(info,address)values('Tom_info','Tom_address');
Query OK, 1 row affected (0.13 sec)

mysql> insert into author_detail(info,address)values('Bob_info','Bob_address');
Query OK, 1 row affected (0.13 sec)

mysql> insert into author_detail(info,address)values('Tom_info_sup','Tom_address_sup');
Query OK, 1 row affected (0.12 sec)

2.再插入關聯表(主表author)的數據,不會出錯
mysql>insert into author(name,mobile,detail_id) values('Tom','13344556677', 1);
Query OK, 1 row affected (0.13 sec)

mysql>insert into author(name,mobile,detail_id) values('Bob','15666882233', 2);
Query OK, 1 row affected (0.12 sec)


# cmd圖例
mysql> select * from author_detail;
+----+--------------+-----------------+
| id | info         | address         |
+----+--------------+-----------------+
|  1 | Tom_info     | Tom_address     |
|  2 | Bob_info     | Bob_address     |
|  3 | Tom_info_sup | Tom_address_sup |
+----+--------------+-----------------+
3 rows in set (0.00 sec)

mysql> select * from author;
+----+------+-------------+------+------+-----------+
| id | name | mobile      | sex  | age  | detail_id |
+----+------+-------------+------+------+-----------+
|  1 | Tom  | 13344556677 | 男   |    0 |         1 |
|  2 | Bob  | 15666882233 | 男   |    0 |         2 |
+----+------+-------------+------+------+-----------+
2 rows in set (0.00 sec)
3.修改關聯表(主表author)
mysql>:update author set detail_id=3 where detail_id=2; #有沒有被其餘數據關聯的數據,就能夠修改

    ## 圖示例
mysql> select * from author;
+----+------+-------------+------+------+-----------+
| id | name | mobile      | sex  | age  | detail_id |
+----+------+-------------+------+------+-----------+
|  1 | Tom  | 13344556677 | 男   |    0 |         1 |
|  2 | Bob  | 15666882233 | 男   |    0 |         3 | # 關聯表的detail已經修改了
+----+------+-------------+------+------+-----------+
2 rows in set (0.00 sec)
4.修改被關聯表(從表author_detail)
mysql> update author_detail set id=10 where id=1;# 沒法修改的,緣由會在後面級聯提到
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`mydb`.`author`, CONSTRAINT `author_ibfk_1` FOREIGN KEY (`detail_id`) REFERENCES `author_detail` (`id`))
5.刪除關聯表的揭露
mysql>: delete from author where detail_id=3;  # 會直接刪除
6.刪除被關聯表中記錄
mysql> delete from author_detail where id=1; # 沒法刪除的
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`mydb`.`author`, CONSTRAINT `author_ibfk_1` FOREIGN KEY (`detail_id`) REFERENCES `author_detail` (`id`))

重點:在對於表設置外鍵且沒有級聯關係的狀況下

  • 表的增長操做:先增長被關聯表記錄,再增長關聯表記錄
  • 表的刪除操做:先刪除關聯表記錄,再刪除被關聯表記錄
  • 表的更新操做:關聯與被關聯表都沒法完成 關聯的外鍵和主鍵 數據更新 - (若是被關聯表記錄沒有被綁定,能夠修改)

總結:以上咱們實現的是一對一的表關係,而且是沒有設置級聯的,從上面的的修改和刪除的部分代碼咱們能夠看到時沒法對被關聯的表進行修改和刪除記錄操做的,後面就會詳細的來說解級聯關係的表

6.2.2 一對一表關係設置外鍵(有級聯關係)

1、設置級聯關係的外鍵語法

create table 關聯表(主表)名(
    字段1 數據類型[約束條件]
    ·
    ·
    字段n 數據類型[約束條件]
    foreign key(主表字段) references 被關聯表名(被關聯表主鍵字段)
    on update cascade  # 兩個表其中一個表數據更新,另外一個表也跟着更新
    on delete cascade # 兩個表其中以一個數據被刪除,另外一個也跟着刪除
);

2、有級聯關係(一對一)案例

咱們依然使用上面的做者和做者詳細信息的案例,而且在已知的建立表規則的條件下去完成

此處沒有錯誤案例分析

1.先刪除上面案列建立的表
mysql>drop table author;
mysql>drop table author_detail;

2.先建立被關聯的表(從表author_detail)
mysql> create table author_detail(
    -> id int primary key auto_increment,
    -> info varchar(256),
    -> address varchar(256)
    -> );
Query OK, 0 rows affected (0.42 sec)

3.再建立關聯表(主表author)
mysql> create table author(
    -> id int primary key auto_increment,
    -> name varchar(64) not null,
    -> mobile char(11) unique not null,
    -> sex enum('男','女') default '男',
    -> age int default 0,
    -> detail_id int unique not null,
    -> foreign key (detail_id) references author_detail(id)
    -> on update cascade # 級聯更新
    -> on delete cascade # 級聯刪除
    -> );
Query OK, 0 rows affected (0.42 sec)


# 插入表數據
# 必須先插入被關聯表數據,有關聯表外鍵關聯的記錄後,關聯表才能夠建立數據
mysql>: insert into author(name,mobile,detail_id) values('Tom','13344556677', 1);  #錯誤

1.向被關聯表author_detail插入數據
mysql>: insert into author_detail(info,address) values('Tom_info','Tom_address');
mysql>: insert into author_detail(info,address) values('Bob_info','Bob_address');
# cmd圖示
mysql> select * from author_detail;
+----+----------+-------------+
| id | info     | address     |
+----+----------+-------------+
|  1 | Tom_info | Tom_address |
|  2 | Bob_info | Bob_address |
+----+----------+-------------+
2 rows in set (0.00 sec)

2.向關聯表author插入數據
mysql>: insert into author(name,mobile,detail_id) values('Tom','13344556677', 1);
mysql>: insert into author(name,mobile,detail_id) values('Bob','15666882233', 2);
mysql> select * from author;
# cmd圖示
+----+------+-------------+------+------+-----------+
| id | name | mobile      | sex  | age  | detail_id |
+----+------+-------------+------+------+-----------+
|  1 | Tom  | 13344556677 | 男   |    0 |         1 |
|  2 | Bob  | 15666882233 | 男   |    0 |         2 |
+----+------+-------------+------+------+-----------+
2 rows in set (0.00 sec)



# 修改關聯表
1.修改關聯表auhtor數據
mysql> update author set detail_id=3 where detail_id=2; # 失敗,被關聯表裏沒有沒有3對應的記錄
mysql>: update author set detail_id=1 where detail_id=2;  # 失敗,1詳情已被其餘的做者關聯
mysql>: insert into author_detail(info,address) values('Tom_info_sup','Tom_address_sup');
mysql>: update author set detail_id=3 where detail_id=2; # 有未被其餘數據關聯的數據,就能夠修改
## cmd圖示
+----+------+-------------+------+------+-----------+
| id | name | mobile      | sex  | age  | detail_id |
+----+------+-------------+------+------+-----------+
|  1 | Tom  | 13344556677 | 男   |    0 |         1 |
|  2 | Bob  | 15666882233 | 男   |    0 |         3 |
+----+------+-------------+------+------+-----------+
2 rows in set (0.00 sec)

2.修改被關聯表 author_detail
mysql>: update author_detail set id=10 where id=1;  # 級聯修改,同步關係關聯表外鍵
## cmd圖示
mysql> select * from author;
+----+------+-------------+------+------+-----------+
| id | name | mobile      | sex  | age  | detail_id |
+----+------+-------------+------+------+-----------+
|  1 | Tom  | 13344556677 | 男   |    0 |        10 |
|  2 | Bob  | 15666882233 | 男   |    0 |         3 |
+----+------+-------------+------+------+-----------+
2 rows in set (0.00 sec)

mysql> select * from author_detail;
+----+--------------+-----------------+
| id | info         | address         |
+----+--------------+-----------------+
|  2 | Bob_info     | Bob_address     |
|  3 | Tom_info_sup | Tom_address_sup |
| 10 | Tom_info     | Tom_address     |
+----+--------------+-----------------+
3 rows in set (0.00 sec)



# 刪除關聯表author
mysql>: delete from author where detail_id=3;  # 直接刪除


# 刪除被關聯表 author_detail
mysql>: delete from author where detail_id=10;  # 能夠刪除對被關聯表author_detail無影響

mysql>: insert into author(name,mobile,detail_id) values('Tom','13344556677', 10);
mysql>: delete from author_detail where id=10;#能夠刪除,將關聯表的記錄對應的10做者詳情級聯刪除

6.2.3 一對多表關係設置外鍵(有級聯關係)

  • 一對多的表關係,外鍵必須放在多的那一方,此時由於時一對多的關係,因此外鍵值不惟一

1、案例

以書和出版社來舉例,一個書對應一個出版社,可是一個出版社能夠出多本書(一對多的關係)

2、實例

此處按照正常的建立流程走,不在演示錯誤案例

# 出版社(publish):id,name,address,phone
1.先建立多的一方,也就是被級聯的表
mysql> create table publish(
    -> id int primary key auto_increment,
    ->     name varchar(64),
    ->     address varchar(256),
    ->     phone char(20)
    -> );
Query OK, 0 rows affected (0.39 sec)

# 書(book):id,name,price,publish_id, author_id
2. 建立一的那一方,也就是關聯表
mysql> create table book(
    -> id int primary key auto_increment,
    ->     name varchar(64) not null,
    ->     price decimal(5, 2) default 0,
    ->     publish_id int,  # 一對多的外鍵不能設置惟一
    ->     foreign key(publish_id) references publish(id)
    ->     on update cascade
    ->     on delete cascade
    -> );
Query OK, 0 rows affected (0.55 sec)




################ 對兩個表插入數據
1.先增長被關聯表(publish)的數據
mysql> insert into publish(name, address, phone) values
    -> ('人民出版社', '北京', '010-1100'),
    -> ('西交大出版社', '西安', '010-1190'),
    -> ('中共教育出版社', '北京', '010-1200');
Query OK, 3 rows affected (0.10 sec)
Records: 3  Duplicates: 0  Warnings: 0

2.再增長關聯表(book)的數據
mysql> insert into book(name, price, publish_id) values
    -> ('西遊記', 16.66, 1),
    -> ('流浪記', 28.66, 1),
    -> ('python從入門到放棄', 2.66, 2),
    -> ('程序員修養之道', 43.66, 3),
    -> ('好好活着', 18.88, 3);
Query OK, 5 rows affected (0.04 sec)
Records: 5  Duplicates: 0  Warnings: 0
### cmd圖示
mysql> select * from book;
+----+--------------------------+-------+------------+
| id | name                     | price | publish_id |
+----+--------------------------+-------+------------+
|  1 | 西遊記                   | 16.66 |          1 |
|  2 | 流浪記                   | 28.66 |          1 |
|  3 | python從入門到放棄        |  2.66 |          2 |
|  4 | 程序員修養之道            | 43.66 |          3 |
|  5 | 好好活着                 | 18.88 |          3 |
+----+--------------------------+-------+------------+
5 rows in set (0.00 sec)

mysql> select * from publish;
+----+-----------------------+---------+----------+
| id | name                  | address | phone    |
+----+-----------------------+---------+----------+
|  1 | 人民出版社            | 北京    | 010-1100 |
|  2 | 西交大出版社          | 西安    | 010-1190 |
|  3 | 中共教育出版社        | 北京    | 010-1200 |
+----+-----------------------+---------+----------+
3 rows in set (0.00 sec)

3.沒有被關聯的字段,插入依舊錯誤
mysql>: insert into book(name, price, publish_id) values ('流浪地球', 33.2, 4);  # 失敗


################ 更新操做
1.直接更新被關聯表的(publish) 主鍵,關聯表(book) 外鍵 會級聯更新
mysql>: update publish set id=10 where id=1;
###cmd圖示
mysql> select * from book;
+----+--------------------------+-------+------------+
| id | name                     | price | publish_id |
+----+--------------------------+-------+------------+
|  1 | 西遊記                   | 16.66 |         10 |
|  2 | 流浪記                   | 28.66 |         10 |
|  3 | python從入門到放棄       |  2.66 |          2 |
|  4 | 程序員修養之道           | 43.66 |          3 |
|  5 | 好好活着                 | 18.88 |          3 |
+----+--------------------------+-------+------------+
5 rows in set (0.00 sec)

2.直接更新關聯表的(book) 外鍵,修改的值對應被關聯表(publish) 主鍵 若是存在,能夠更新成功,反之失敗
mysql>: update book set publish_id=2 where id=4;  # 成功,此時被級聯表的值是不受印象的
mysql>: update book set publish_id=1 where id=4;  # 失敗,由於外鍵字段沒有這個值


############ 刪除操做
1.刪被關聯表,關聯表會被級聯刪除
mysql>: delete from publish where id = 2;

2.刪關聯表,被關聯表不會發生變化
mysql>: delete from book where publish_id = 3;
# 假設:書與做者也是 一對多 關係,一個做者能夠出版多本書
create table book(
    id int primary key auto_increment,
    name varchar(64) not null,
    price decimal(5, 2) default 0,
    publish_id int,  # 一對多的外鍵不能設置惟一
    foreign key(publish_id) references publish(id)
    on update cascade
    on delete cascade
    
    # 創建與做者 一對多 的外鍵關聯
    author_id int,  
    foreign key(author_id) references author(id)
    on update cascade
    on delete cascade
);

6.2.4 多對多的表關係設置外鍵(有級聯關係)

  • 多對多的關係表,必定要建立第三張表來存儲他們的關係,關係表中的每個外鍵值不惟一
  • 能夠設置多個外鍵聯合惟一

1、案例

此處以學生表和課程表爲案例,完成 學生表 與 課程表 的 多對多 表關係的建立,並完成數據測試

  • 學生表屬性:sid(學生學號),sname(學生姓名),sage(學生年齡)
  • 課程表屬性:cid(課程號),cname(課程名)
  • 關係表屬性:id,stu_id(學號), cus_id(課程號)

2、實例

##############建立表
1.建立被關聯學生表student
create table student(
    sid int primary key auto_increment,
    sname char(8) not null,
    sage int unsigned default 18
);

2.建立被關聯課程表course
create table course(
    cid int primary key auto_increment,
    cname char(8) not null
);

3.建立學生和課程關係表
create table stu_cus(
    id int primary key auto_increment,
    stu_id int,
    foreign key(stu_id) references student(sid)
    on update cascade
    on delete cascade,
    
    cus_id int,
    foreign key(cus_id) references course(cid)
    on update cascade
    on delete cascade,
    unique(stu_id,cus_id)
);

##################插入表數據
1.student表添加數據
insert into student values(1,'xichen',18),(2,'chen',19),(3,'cecilia',20);
2.courset表添加數據
insert into course values(1,'python'),(2,'linux'),(3,'java'),(4,'go語言');
3.關係表stu_cus添加數據,必須在被關聯的兩張表已經有數據後再添加數據
insert into stu_cus values(1,1,1),(2,1,4),(3,2,1),(4,3,2),(5,3,4);
### cmd圖示
mysql> select * from student;
+-----+---------+------+
| sid | sname   | sage |
+-----+---------+------+
|   1 | xichen  |   18 |
|   2 | chen    |   19 |
|   3 | cecilia |   20 |
+-----+---------+------+
3 rows in set (0.00 sec)

mysql> select * from course;
+-----+----------+
| cid | cname    |
+-----+----------+
|   1 | python   |
|   2 | linux    |
|   3 | java     |
|   4 | go語言   |
+-----+----------+
4 rows in set (0.00 sec)

mysql> select * from stu_cus;
+----+--------+--------+
| id | stu_id | cus_id |
+----+--------+--------+
|  1 |      1 |      1 |
|  2 |      1 |      4 |
|  3 |      2 |      1 |
|  4 |      3 |      2 |
|  5 |      3 |      4 |
+----+--------+--------+
5 rows in set (0.00 sec)

######################被關聯表更新數據
1.向student學生表和course課程表添加數據不會影響關係表stu_cus
insert into student(sname,sage) values('xuchen',20);
insert into course(cname) values('c++');
####cmd測試
mysql> select * from stu_cus;
+----+--------+--------+
| id | stu_id | cus_id |
+----+--------+--------+
|  1 |      1 |      1 |
|  2 |      1 |      4 |
|  3 |      2 |      1 |
|  4 |      3 |      2 |
|  5 |      3 |      4 |
+----+--------+--------+
5 rows in set (0.00 sec)


#########################修改關聯表
1.修改student學生表和course課程表 會影響到關係表
update student set sid=5 where sid=3;# 若是修改student的id表裏已存在,則不能修改
###cmd測試  關係表中原來stu_id爲3的就都級聯更新爲5
mysql> select * from stu_cus;
+----+--------+--------+
| id | stu_id | cus_id |
+----+--------+--------+
|  1 |      1 |      1 |
|  2 |      1 |      4 |
|  3 |      2 |      1 |
|  4 |      5 |      2 |
|  5 |      5 |      4 |
+----+--------+--------+
5 rows in set (0.00 sec)


########################刪除關聯表
1.刪除student學生表和course課程表數據,關係表也會級聯刪除
delete from course where cid=1;
####cmd測試  關係表中原來cus_id爲1的就都級聯刪除
mysql> select * from stu_cus;
+----+--------+--------+
| id | stu_id | cus_id |
+----+--------+--------+
|  2 |      1 |      4 |
|  4 |      5 |      2 |
|  5 |      5 |      4 |
+----+--------+--------+
3 rows in set (0.00 sec)
相關文章
相關標籤/搜索