產(chǎn)品經(jīng)理從0開始學(xué)SQL(五)-表設(shè)計(jì)
目錄
1、數(shù)據(jù)庫約束與常見操作
2、建表規(guī)范
ps:以下講解均基于mysql語言。
數(shù)據(jù)庫約束與常見操作
一、主鍵
我們知道,一個表由n行記錄組成。
1、概述
關(guān)系表都有一個約束:每一行記錄必須要有某個字段來唯一標(biāo)識,能唯一標(biāo)記記錄的字段,稱為主鍵。
假設(shè)有一張學(xué)生表:t_student
| id | name | class_id | mobile |
|---|---|---|---|
| 1 | 張三 | 2 | 130xxx |
| 2 | 李四 | 4 | 140xxx |
| 3 | 陳紅 | 3 | 150xxx |
上面這張表,id是主鍵,我們可以通過id來區(qū)分出每一個同學(xué):
id=1是張三,id=2是李四,id=3是陳紅
一個表必須要有主鍵。我們可以在建表的時候,用primary key標(biāo)識。比如:
create table t_student ( id int, name varchar(10), primary key (id));
2、主鍵字段的選擇
當(dāng)表已經(jīng)開始使用并錄入數(shù)據(jù)后,最好不要再做更改了,因?yàn)楸淼闹麈I可能已經(jīng)在其他表里用做外鍵關(guān)聯(lián)或者已經(jīng)在業(yè)務(wù)邏輯中使用。
所以定義主鍵最好不要使用業(yè)務(wù)字段,業(yè)務(wù)字段發(fā)生變更的概率比較大,比如學(xué)生的手機(jī)號碼、學(xué)生的身份證都是可能發(fā)生變化的。
我們可以使用默認(rèn)的自增字段來做主鍵,比如student表的id。
也可以使用基于時間和空間生成的uuid來做主鍵,uuid一般是業(yè)務(wù)邏輯里面生成來動態(tài)插入數(shù)據(jù)表。
3、聯(lián)合主鍵
主鍵可以使用多個字段來標(biāo)記。但是不太建議使用。這樣在以后處理表關(guān)系或者業(yè)務(wù)邏輯時,會增加復(fù)雜度。
二、外鍵
假設(shè)有一張學(xué)生表:t_student
| id | name | class_id | mobile |
|---|---|---|---|
| 1 | 張三 | 2 | 130xxx |
| 2 | 李四 | 4 | 140xxx |
| 3 | 陳紅 | 3 | 150xxx |
還有一張班級表:t_class
| id | class_name |
|---|---|
| 1 | 1班 |
| 2 | 2班 |
| 3 | 3班 |
| 4 | 4班 |
我們已經(jīng)能通過id來識別張三、李四。那么我們怎么識別張三屬于哪個班級,李四屬于哪個班級呢?這時我們可以使用外鍵。
在t_student表增加一列叫class_id來表示班級id。
我們通過關(guān)系:t_student.class_id=t_class.id可以看出,張三在1班,李四在4班,陳紅在3班。
通過外鍵我們可以看出,這2張表是一個1對多的關(guān)系。這里的“多”指的是學(xué)生表,“1”指的是班級表,含義是一個學(xué)生只可以對應(yīng)一個班級,但是一個班級可以對應(yīng)多個學(xué)生。
那如果是多對多的關(guān)系該如何實(shí)現(xiàn)呢?假設(shè)有一張學(xué)生選修的課程表:t_course
| id | course_name |
|---|---|
| 1 | 高等數(shù)學(xué) |
| 2 | 物理 |
| 3 | 政治 |
| 4 | 算法 |
一個學(xué)生可選修多門課程,一個課程也可以被多名學(xué)生選擇學(xué)習(xí)。這是一個多對多的關(guān)系。
一般會通過一個中間表來實(shí)現(xiàn)。
我們建立一個中間表叫做:t_student_course
| id | course_id | student_id |
|---|---|---|
| 1 | 1 | 1 |
| 1 | 1 | 2 |
| 2 | 2 | 3 |
| 2 | 2 | 4 |
| 3 | 3 | 1 |
| 4 | 4 | 2 |
表里一般要存儲2個表的主鍵,如上的course_id和student_id。從表中我們就可以看出,學(xué)生id=1的張三選修了兩門課程,分別是數(shù)學(xué)和政治。學(xué)生id=2的李四也選修了兩門課程,分別是數(shù)據(jù)和算法。
還剩下一種表關(guān)系是1對1的關(guān)系,假設(shè)還有一張學(xué)生信息明細(xì)表,存儲的是學(xué)生更詳細(xì)的信息的表:t_student_detail
| id | student_id | address | age |
|---|---|---|---|
| 1 | 1 | 深圳南山 | 男 |
| 2 | 2 | 深圳福田 | 男 |
| 3 | 3 | 深圳龍崗 | 女 |
我們可以看出,一個學(xué)生對應(yīng)一個詳細(xì)信息。但是如果t_student_detail表里面只有一個字段或者2個字段的話,根據(jù)業(yè)務(wù)情況,也可以把這些字段納入到t_student表中。
其實(shí)上述的學(xué)生詳細(xì)明細(xì)表的做法,是一個提升表查詢效率的做法。當(dāng)t_student表的數(shù)據(jù)量比較大的時候,而且查詢學(xué)生信息可能往往只是那幾個字段,就可以通過分表的方式去提升查詢性能。
小結(jié):表之間的關(guān)系有3種,分別是1對1,1對多,多對多。1對1可以通過增加一個字段或者建立另一張表通過外鍵關(guān)聯(lián)。1對多可以通過建立另一張表通過外鍵關(guān)聯(lián)。而多對多可以通過建立一張中間表和其他2張表的外鍵關(guān)聯(lián)。
三、索引
索引按用途可以分為2種,一種是用于提升查詢速度的查詢索引,另一種是約束唯一性作用的唯一索引。
1、查詢索引
一張數(shù)據(jù)表中,可能有成千上萬的數(shù)據(jù),如果想提高查詢速度,那么通過給字段創(chuàng)建索引是提高查詢速度的一種方式。
如果t_student表中,name是經(jīng)常要查詢的字段,那我們可以給name創(chuàng)建一個索引。
ALTER TABLE t_student ADD INDEX idx_name (name)
2、唯一索引
唯一索引表示的是字段的值是唯一的。
比如學(xué)生的手機(jī)號碼,身份證這些業(yè)務(wù)字段,都是唯一的,如果給這些字段加上唯一索引約束,那么當(dāng)你往學(xué)生表里插入重復(fù)的手機(jī)號碼或者身份證時,數(shù)據(jù)庫就會報(bào)錯阻止你的操作,起到保護(hù)數(shù)據(jù)唯一性的作用。
對單個字段添加唯一索引:mobile字段
ALTER TABLE t_student ADD UNIQUE INDEX uni_mobile (mobile);
對多個字段添加聯(lián)合唯一索引:mobile和card_id字段
ALTER TABLE t_student ADD UNIQUE INDEX uni_mobile_card (mobile,card_id);
四、默認(rèn)值
我們可以給字段設(shè)置默認(rèn)值,但是默認(rèn)值跟數(shù)據(jù)類型必須是匹配的。比如你是一個int整型,不能設(shè)置一個字符串類型的值。
比如設(shè)置時間字段的默認(rèn)值為當(dāng)前時間戳:
create table t_student ( create_time timestamp default current_timestamp );
五、NOT NULL 約束
null不是數(shù)據(jù)類型,它是列的一個屬性。
null表示的是空,如果你不允許你的字段值為空,則添加not null約束
比如約束學(xué)生表的名字不能為空:
create table t_student (name VARCHAR(22) NOT NULL)
建表規(guī)范
建表三范式可能大家都知道。一般建表都要遵守三范式原則。
一、第一范式
要求有主鍵,并且要求每一個字段都遵守原子性不可再分。
二、第二范式
滿足第一范式的前提下,要求所有非主鍵字段完全依賴主鍵,不能產(chǎn)生部分依賴。
舉個例子:假設(shè)有一張學(xué)生表:t_student
| 學(xué)生編號 | 老師編號 | 學(xué)生姓名 | 老師姓名 |
|---|---|---|---|
| s1001 | t1001 | 張三 | 葉老師 |
| s1002 | t1001 | 李四 | 葉老師 |
| s1003 | t1003 | 陳紅 | 李老師 |
這個表以學(xué)生編號和老師編號為聯(lián)合主鍵。
該表會出現(xiàn)大量的冗余,冗余字段為“學(xué)生姓名”和“教師姓名”,出現(xiàn)冗余主要是學(xué)生姓名部分依賴了主鍵的一個字段學(xué)生編號,而沒有依賴教師編號,而教師姓名部分依賴了主鍵的一個字段教師編號,這就是第二范式部分依賴。
所以這張表是不合理的,學(xué)生和老師之間的關(guān)系應(yīng)該是多對多的關(guān)系,我們應(yīng)該通過建立3張表來實(shí)現(xiàn),分別是
t_student(學(xué)生表)
t_teacher(老師表)
t_student_teacher(學(xué)生老師中間表)
三、第三范式
滿足第二范式的前提下,所有非主鍵字段和主鍵字段之間不能產(chǎn)生傳遞依賴。某個字段依賴于主鍵,而有其他字段依賴于該字段。這就是傳遞依賴。(不詳細(xì)描述了,道理跟第二范式的例子類似)
---- END ----
免費(fèi)星球:建立了一個產(chǎn)品+技術(shù)資料庫星球,每周會定期更新資料庫,內(nèi)容包括最新的行業(yè)報(bào)告、電子書、原型等,關(guān)注公眾號并回復(fù)【星球】免費(fèi)進(jìn)入!
以下是星球資料部分截圖:


?? 愛心三連擊
1、看到這里了就點(diǎn)個在看支持下吧,你的點(diǎn)贊/在看/分享是我持續(xù)創(chuàng)作的動力。
2、關(guān)注公眾號【產(chǎn)品的技術(shù)小課】,回復(fù)【加群】加入產(chǎn)品技術(shù)交流群
3、也可添加我微信【yss627144】,一起成長。
