欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MySQL主鍵約束和外鍵約束詳解

 更新時(shí)間:2023年03月13日 09:51:26   作者:程序猿教你打籃球  
主鍵約束,說(shuō)白了就是 not null + unique,主鍵也是在插入數(shù)據(jù)的時(shí)候先進(jìn)行查詢(xún),而 MySQL 則會(huì)對(duì) unique,primary key 這樣的列自動(dòng)的添加索引(后續(xù)介紹),來(lái)提高查詢(xún)的效率,這篇文章主要介紹了MySQL主鍵約束和外鍵約束,需要的朋友可以參考下

1、PRIMARY KEY

上期我們講述了 not null 和 unique 約束,而本期的第一個(gè)約束就是這倆的結(jié)合體,也成為主鍵約束。

主鍵約束,說(shuō)白了就是 not null + unique,主鍵也是在插入數(shù)據(jù)的時(shí)候先進(jìn)行查詢(xún),而 MySQL 則會(huì)對(duì) unique,primary key 這樣的列自動(dòng)的添加索引(后續(xù)介紹),來(lái)提高查詢(xún)的效率。

● 在實(shí)際開(kāi)發(fā)中,大部分的表,一般都會(huì)帶有一個(gè)主鍵,主鍵往往是一個(gè)整數(shù)表示的 id。

create table student (
    id int primary key,
    name varchar(10)
);

只要你給改列設(shè)置了主鍵,意味著后續(xù)插入的數(shù)據(jù),既不能重復(fù),也不能為空! 

● 在 MySQL 中,一個(gè)表中只能有一個(gè)主鍵,不能有多個(gè)。

create table student (
    id int primary key,
    name varchar(10) primary ke
);
-- ERROR 1068 (42000): Multiple primary key defined

● 雖然主鍵不能有多個(gè),但支持將多個(gè)列放到一起,共同作為主鍵,稱(chēng)為聯(lián)合主鍵。

create table student (
    id int,
    name varchar(10),
    primary key (id, name)
);
desc student;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   | PRI | NULL    |       |
| name  | varchar(10) | NO   | PRI | NULL    |       |
+-------+-------------+------+-----+---------+-------+
-- 2 rows in set (0.00 sec)

這樣我們就能發(fā)現(xiàn) Key 這一列有兩個(gè) PRI 了,PRI 是主鍵的簡(jiǎn)寫(xiě),表示是主鍵字段,同時(shí)也能看到 Null 這一列為 NO,所以主鍵包含了 not null 和 unique 的特性。

● 主鍵還有一個(gè)非常常用的用法,使用 MySQL 自帶的自增主鍵作為主鍵的值。

create table student (
    id int primary key auto_increment,
    name varchar(10)
);

這里我們就來(lái)插入數(shù)據(jù)試一試:

insert into student value 
    (88, '李四'),
    (12, '張三');

這里仍然可以插入成功,由此能發(fā)現(xiàn)設(shè)置了自增主鍵仍然能自定義值,那么下面如果不自定義 id 的值呢?會(huì)自動(dòng)生成多少呢?

insert into student(name) values('王五');
-- Query OK, 1 row affected (0.00 sec)
 
select * from student;
+----+--------+
| id | name   |
+----+--------+
| 12 | 張三   |
| 88 | 李四   |
| 89 | 王五   |
+----+--------+
-- 3 rows in set (0.00 sec)

注意:這里可以看到,我們插入是 李四,張三,但是查詢(xún)卻是 張三在前李四在后,所以 MySQL 并未保證插入順序和取出是順序是一致的!

再者這里可以發(fā)現(xiàn),自增主鍵插入數(shù)據(jù)對(duì)應(yīng)字段不給值時(shí),使用最大值+1。那如果我把王五刪了,再次插入一條數(shù)據(jù),自增主鍵會(huì)是多少呢?

delete from student where name = '王五';
-- Query OK, 1 row affected (0.00 sec)
 
insert into student(name) values('趙六');
-- Query OK, 1 row affected (0.00 sec)
 
select * from student;
+----+--------+
| id | name   |
+----+--------+
| 12 | 張三   |
| 88 | 李四   |
| 90 | 趙六   |
+----+--------+
-- 3 rows in set (0.00 sec)

看到?jīng)]!并不是按照當(dāng)前列的最大值來(lái)自增主鍵的,你可以理解為 MySQL 有個(gè)記錄主鍵最大值的玩意,是按照這個(gè)之前主鍵最大值自增的!刪除了數(shù)據(jù),不影響主鍵的最大值!

我們?cè)賮?lái)看一個(gè)操作:

insert into student values(null, '孫七');

這個(gè)操作并不是插入 null 數(shù)據(jù),而是交給數(shù)據(jù)庫(kù)使用自增主鍵!

這里又有一個(gè)疑問(wèn)了,如果數(shù)據(jù)量太大,一個(gè)服務(wù)器存不下那么多數(shù)據(jù)怎么辦?那就要采用分庫(kù)分表的操作了,多臺(tái)服務(wù)器來(lái)存儲(chǔ)了,本質(zhì)上就是把一張大表,分成多張小表,每個(gè)服務(wù)器分別只存一部分大大數(shù)據(jù),這就可以理解成分布式處理了,

問(wèn)題來(lái)了,上述這樣的情況,還能使用自增主鍵嗎?

這里涉及到一個(gè) "分布式系統(tǒng)中唯一 id 生成算法" ,也就是全局唯一 id,常見(jiàn)的即:

實(shí)現(xiàn)公式:時(shí)間戳+主機(jī)編號(hào)+隨機(jī)因子 => 全局唯一的 id。

當(dāng)然感興趣的可以下來(lái)進(jìn)一步了解下,這里就不過(guò)多闡述了。

2、FOREIGN KEY

外鍵約束,說(shuō)白了就是兩個(gè)表之間相互約束。

注意:外鍵是用于關(guān)聯(lián)其他表的主鍵或唯一鍵!

foreign key (字段名) references 主表(列)

這里我們舉個(gè)例子,在學(xué)校里,有很多個(gè)班級(jí),每個(gè)班級(jí)里有很多學(xué)生,也就是一個(gè)學(xué)生對(duì)應(yīng)一個(gè)班級(jí),一個(gè)班級(jí)對(duì)應(yīng)多個(gè)學(xué)生,假設(shè)某某學(xué)校,只有三個(gè) java 班級(jí),分別是 java1班,java2班,java3班,每個(gè)班級(jí)又有若干個(gè)學(xué)生,現(xiàn)在開(kāi)學(xué)了,學(xué)生去學(xué)校報(bào)道, 報(bào)道的時(shí)候呢會(huì)登記你的班級(jí),志愿者一問(wèn),同學(xué)你哪個(gè)班的呀?我說(shuō):我 java2 班的,于是順利登記成功,后面又來(lái)了一個(gè)同學(xué),同樣的問(wèn)題,同學(xué)你哪個(gè)班的呀?我 java6班,志愿者一查詢(xún),咱學(xué)校沒(méi)有 java6班呀,于是那個(gè)同學(xué)就被老師帶走調(diào)查了...

上述只是一個(gè)故事,可以把我們自己想象成一條數(shù)據(jù),當(dāng)然登記信息肯定不僅僅是登記班級(jí),還有有 學(xué)號(hào) 姓名 性別 身份證 班級(jí)號(hào)...  而這里我們的班級(jí)號(hào)不是隨便哪個(gè)都可以的,是有固定的幾個(gè)班級(jí)號(hào),如果這幾個(gè)班級(jí)號(hào)中沒(méi)有你報(bào)的班級(jí)號(hào),那么你的信息,就錄不上去,也就是一個(gè)錯(cuò)誤的信息。假設(shè)這幾個(gè)班級(jí)號(hào)放在一起,對(duì)應(yīng)一張班級(jí)表,咱們登記登記的信息,對(duì)應(yīng)學(xué)生表, 那么就是兩張表之間指定字段的約束。

有了上述鋪墊,我們就來(lái)用代碼來(lái)理解一下:

● 首先創(chuàng)建一張班級(jí)表 classes,id 為主鍵:

create table classes (
    id int primary key,
    name varchar(10)
);

這樣 classes 班級(jí)表就建好了,這里有個(gè)問(wèn)題,為什么 id 要作為主鍵呢?

答:首先這里的 id 對(duì)應(yīng)班級(jí)號(hào),name 是班級(jí)名稱(chēng),而外鍵是用于關(guān)聯(lián)其他表的主鍵或唯一鍵,所以說(shuō)這里的 id 字段,要不是主鍵,要不是唯一鍵。

未來(lái)學(xué)生表會(huì)有一個(gè)字段擁有外鍵屬性,來(lái)關(guān)聯(lián)這個(gè) classes 的 id 字段!??!

● 創(chuàng)建學(xué)生表 student 指定 classId 為外鍵,關(guān)聯(lián) classes 表中 id 字段

create table student (
    id int,
    name varchar(10),
    sex varchar(1),
    classId int,
    foreign key (classId) references classes(id)
);

這段 sql 語(yǔ)句最后一條,foreign key (classId) references classes(id),這條語(yǔ)句表示,將創(chuàng)建的 student 表中 classId 字段作為外鍵,于 classes 表中 id 字段關(guān)聯(lián)!

這兩張表是創(chuàng)建好了,現(xiàn)在得創(chuàng)建數(shù)據(jù)了,為 classes 表中創(chuàng)建三個(gè)班級(jí)數(shù)據(jù):

insert into classes value 
    (1, 'java1班'),
    (2, 'java2班'),
    (3, 'java3班');

這樣就能表示有存在了三個(gè)班級(jí),分別是 1班,2班,3班,如果接下來(lái)我去登記信息,錄入的班級(jí)在這三個(gè)班之中,那就毫無(wú)問(wèn)題:

insert into student values (230115, '籃球哥', '男', 2);
-- Query OK, 1 row affected (0.00 sec)

這里是不是就如同我們上面舉例說(shuō)明的這樣,我是 java2 班的,而 classId 錄入了一個(gè) 2,關(guān)聯(lián) classes 的 id 字段 2,對(duì)應(yīng)的就是 java2 班。

那如果后來(lái)的同學(xué),錄入一個(gè) java6 班呢?

insert into student values (230205, '小王', '男', 6);
-- ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`demo`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`classId`) REFERENCES `classes` (`id`))

那么此處的外鍵約束的含義,要求了 student 里的 classId 務(wù)必要在 classes 表的 id 列中存在!

相信看到這,大家都能明白外鍵約束的作用了,student 表中的數(shù)據(jù),要依賴(lài) classes 表的數(shù)據(jù),而 classes 表的數(shù)據(jù)要對(duì) student 表產(chǎn)生約束力,就像 父親 對(duì) 孩子 有約束力。此處起到約束作用的表我們稱(chēng)為 "父表",被約束的表我們稱(chēng)為 "子表"。

看到這里啊,說(shuō)白了就是 父表 對(duì) 子表 起到了約束作用,限制了約束的字段的取值.

這里我不禁想到一句話(huà),當(dāng)你在凝視深淵的時(shí)候,深淵也在凝視你!

我們表面上看確實(shí)是 父表 對(duì) 子表 起到約束,但反過(guò)來(lái)其實(shí) 子表 也限制著 父表!

這里我們嘗試刪除父表中 id 為 2 的數(shù)據(jù),也就是刪除 java1班:

delete from classes where id = 2;
-- ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`demo`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`classId`) REFERENCES `classes` (`id`))

發(fā)現(xiàn)報(bào)錯(cuò)了,其實(shí)我們想也能想到,如果真能刪除,那子表中 classesId = 2 的那一條數(shù)據(jù)不就尷尬了嗎?那這外鍵約束建了又像沒(méi)有建一樣,所以就僵住了,顯然是不允許這樣的情況發(fā)生的!

當(dāng)然 classes 表中 id 為 1 的數(shù)據(jù)可以刪除,因?yàn)?子表 并不存在 classId 為 1 的數(shù)據(jù)嘛:

delete from classes where id = 1;
-- Query OK, 1 row affected (0.00 sec)

問(wèn)題:可以先建子表再建父表嗎?

顯然是不行的呀,當(dāng)你建子表指定外鍵約束的時(shí)候,你父表都沒(méi)有,怎么建約束?

3、表的設(shè)計(jì)

表的設(shè)計(jì)算是一個(gè)比較抽象的概念,有了一定經(jīng)驗(yàn)后,會(huì)更好理解,結(jié)合后期的項(xiàng)目設(shè)計(jì),再來(lái)理解表設(shè)計(jì),可能會(huì)更好,這里就簡(jiǎn)單介紹下常見(jiàn)設(shè)計(jì)。

3.1 一對(duì)一

比如說(shuō)我們每個(gè)人都有的身份證,每個(gè)身份證id,就對(duì)應(yīng)一個(gè)人,這就是一對(duì)一關(guān)系。

這種一對(duì)一關(guān)系可以如何創(chuàng)建表呢?

● 第一種方案

create table person (
    id int primary key,
    name varchar(10),
    address varchar(50),
    sex varchar(1)
);

把身份證id和姓名直接放在一張表里.

● 第二種方案

create table person (
    id int primary key,
    name varchar(10)
);
create table account (
    accountId int primary key,
    personName varchar(10),
    address varchar(50),
    sex varchar(1),
    id int,
    foreign key (id) references person(id)
);

第二種方案則是身份證號(hào)和姓名放在不同的表里,相互關(guān)聯(lián)。

3.2 一對(duì)多

這個(gè)例子很像我們之前說(shuō)過(guò)的,一個(gè)班級(jí)有多個(gè)學(xué)生,一個(gè)學(xué)生對(duì)應(yīng)一個(gè)班級(jí),這里就不在贅述。

3.3 多對(duì)多

比如說(shuō)學(xué)校的一門(mén)課程,可以被多名學(xué)生選修,而一名學(xué)生可以選修多門(mén)課程,這就是多對(duì)多的關(guān)系:

這里我們只需要讓 student 表 studentId 字段 約束 student_course 表的 studentId 字段,以及 course 表  courseId 字段約束 student_course 表的 courseId 字段即可。

到此這篇關(guān)于MySQL主鍵約束和外鍵約束的文章就介紹到這了,更多相關(guān)mysql主鍵約束和外鍵約束內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 修改MySQL所有表的編碼或修改某個(gè)字段的編碼步驟詳解

    修改MySQL所有表的編碼或修改某個(gè)字段的編碼步驟詳解

    這篇文章主要給大家介紹了關(guān)于修改MySQL所有表的編碼或修改某個(gè)字段編碼的相關(guān)資料,在進(jìn)行數(shù)據(jù)庫(kù)編碼更改之前,需要先確定目標(biāo)編碼格式,常見(jiàn)的編碼格式有UTF-8、GBK等,需要的朋友可以參考下
    2023-12-12
  • MySQL學(xué)習(xí)第五天 MySQL數(shù)據(jù)庫(kù)基本操作

    MySQL學(xué)習(xí)第五天 MySQL數(shù)據(jù)庫(kù)基本操作

    MySQL學(xué)習(xí)第五天我們將針對(duì)MySQL數(shù)據(jù)庫(kù)進(jìn)行基本操作,創(chuàng)建、修改、刪除數(shù)據(jù)庫(kù)等一系列操作進(jìn)行學(xué)習(xí),感興趣的小伙伴們可以參考一下
    2016-05-05
  • MySQL 使用 SSL 連接配置詳解

    MySQL 使用 SSL 連接配置詳解

    本文給大家分享的是如何配置MySQL支持SSL連接方式的方法以及在docker中配置的具體案例,有需要的小伙伴可以參考下
    2016-12-12
  • MySQL存儲(chǔ)過(guò)程的創(chuàng)建使用以及實(shí)現(xiàn)數(shù)據(jù)快速插入

    MySQL存儲(chǔ)過(guò)程的創(chuàng)建使用以及實(shí)現(xiàn)數(shù)據(jù)快速插入

    因最近想要測(cè)試一下MySQL百萬(wàn)級(jí)數(shù)據(jù)處理過(guò)程,所以要一次對(duì)數(shù)據(jù)庫(kù)快速插入大量數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于MySQL存儲(chǔ)過(guò)程的創(chuàng)建使用以及實(shí)現(xiàn)數(shù)據(jù)快速插入的相關(guān)資料,需要的朋友可以參考下
    2023-03-03
  • mysql線(xiàn)上查詢(xún)前要注意資源限制的實(shí)現(xiàn)

    mysql線(xiàn)上查詢(xún)前要注意資源限制的實(shí)現(xiàn)

    在數(shù)據(jù)庫(kù)管理中,限制查詢(xún)資源是避免單個(gè)查詢(xún)消耗過(guò)多資源導(dǎo)致系統(tǒng)性能下降的重要手段,本文就來(lái)介紹了mysql線(xiàn)上查詢(xún)前要注意資源限制的實(shí)現(xiàn),感興趣的可以了解一下
    2024-10-10
  • MySQL事務(wù)處理與應(yīng)用簡(jiǎn)析

    MySQL事務(wù)處理與應(yīng)用簡(jiǎn)析

    事務(wù)處理在各種管理系統(tǒng)中都有著廣泛的應(yīng)用,比如人員管理系統(tǒng),很多同步數(shù)據(jù)庫(kù)操作大都需要用到事務(wù)處理。這篇文章主要介紹了MySQL事務(wù)處理,需要的朋友可以參考下
    2014-06-06
  • MySQL的commit是如何commit源碼解析

    MySQL的commit是如何commit源碼解析

    這篇文章主要為大家介紹了MySQL的commit是如何commit源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • 與MSSQL對(duì)比學(xué)習(xí)MYSQL的心得(六)--函數(shù)

    與MSSQL對(duì)比學(xué)習(xí)MYSQL的心得(六)--函數(shù)

    這一節(jié)主要介紹MYSQL里的函數(shù),MYSQL里的函數(shù)很多,我這里主要介紹MYSQL里有而SQLSERVER沒(méi)有的函數(shù)
    2014-08-08
  • MySQL分區(qū)表管理命令匯總

    MySQL分區(qū)表管理命令匯總

    這篇文章主要分享了MySQL分區(qū)表管理命令匯總,分區(qū)是一種表的設(shè)計(jì)模式,正確的分區(qū)可以極大地提升數(shù)據(jù)庫(kù)的查詢(xún)效率,完成更高質(zhì)量的SQL編程。但是如果錯(cuò)誤地使用分區(qū),那么分區(qū)可能帶來(lái)毀滅性的的結(jié)果,下面我們就來(lái)看看分區(qū)表那些常用的管理命令,需要的朋友可以參考下
    2022-03-03
  • MySql 5.6.36 64位綠色版安裝圖文教程

    MySql 5.6.36 64位綠色版安裝圖文教程

    這篇文章主要介紹了MySql 5.6.36 64位綠色版安裝圖文教程,需要的朋友可以參考下
    2017-05-05

最新評(píng)論