表的約束:表中一定要有各種約束,通過約束,讓未來插入數據庫表中的數據是符合預期的。約束本質是通過技術手段,倒逼程序員插入正確的數據。即,站在mysql的視角,凡是插入進來的數據,都是符合數據約束的!
約束的最終目標:保證數據的完整性和可預期性。
空屬性
兩個值:null(默認的)和not null(不為空)
數據庫默認字段基本都為空,但是實際開發中,盡可能保證字段不為空,因為數據為空,沒辦法參與運算。
例:
創建一個班級表,包含班級名和班級所在的教室。
正常的邏輯是這樣的:
- 如果沒有班級名,則不知道在哪個班級
- 如果沒有教室,則不知道在哪上課
所以在設計數據庫表的時候,一定要在表中進行限制,滿足上面條件的數據就不能插入到表中。者就是約束!
如果對班級和教室不加約束,可以為空(默認的)。
插入數據的時候,沒有給班級名或教室也能插入成功,插入的數據不符合不符合預期。顯然這種不加約束的做法是不符合邏輯的。
對班級和教室進行約束,不能為空。
插入數據的時候,沒有給班級名或教室名,就插入失敗;能插入的數據一定是給了班級名和教室,一定是符合預期的。所以建表的時候一定要加約束。
defalut
如果設置了。用戶插入的時候,如果顯示的有插入的有具體的數據,就使用用戶插入的數據;如果沒有就用默認設置的。
如果設置了默認值,可以省略該字段,就使用默認值,只有設置了default的字段才能省略。
那么not null 和 default 有什么區別呢?
- 如果沒有明確指定一列要插入,用的是default,如果建表中,對應的列默認沒有設置default,無法不直接插入。
- default 和 not null 并不沖突,而是互相補充的。
- not null:當用戶想插入的時候,無非插入的數據要么是 null,要么是合法數據,如果字段為 not null,插入 null 則報錯。
- default:當用戶忽略了某一列的時候,如果該列設置了默認值則使用默認值,如果沒有設置,直接報錯。用于為列指定一個默認值。
總結:
- 如果用戶想顯示的插入數據,就是 not null 在約束,如果為 not null ,則插入數據不能為null。
- 如果用戶不顯示的插入數據,就是 default 在約束,如果沒有設置 default ,則該列不能直接插入。
建t14表的時候,字段沒有指定 null 和 default,為什么也能直接插入呢?
MySQL會對sql指令優化。默認指定字段為 null、default 默認值也為 null。
列描述
列描述:comment,沒有實際含義,專門用來描述字段,會根據表創建的語句保存,用來給程序員或DBA來進行了解表字段。
zerofill
看下面這張表。
mysql會對sql語句做優化,將字段a int unsigned 類型優化為 int(10)unsigned;將字段b int 類型優化為 int(11)。10和11表示什么?其實沒有zerofill括號內的數字是沒有意義的。
括號內的數字表示數據的寬度。為什么int unsigned默認為10呢?
因為無符號整數表示-2147483648 到 2147483647,最大為21億多,10位就足夠將一個整數的數據位全部表示出來了;int 默認為11,因為有符號整數表示0 到 4294967295,最大為42億多,加上符號位11位,11位就足夠將一個有符號的整數的數據位全部表示出來了,
但是對列添加了zerofill屬性后,顯示的結果就有所不同了。修改t16a字段的屬性。
可以看到,本來應該顯示為1的,添加zerofill后,顯示成了0001,這就是zerofill屬性的作用,如果插入數據的寬度小于設定的寬度(這里設置的是4),自動填充0;如果插入寬度大于設定的值,顯示的還是它本身。
要注意的是,這只是最后顯示的結果,在MySQL中實際存儲的還是插入的數據本身。
主鍵
primary key:用來唯一的約束該字段里面的數據,不能重復,不能為空,一張表中最多只有一個主鍵。
- 創建表的時候直接在字段上指定主鍵
- 主鍵約束:主鍵對應的字段不能重復,一旦重復,操作失敗
- 刪除主鍵
- 創建表時沒有指定主鍵,可以在創建表之后追加主鍵。如果創建表之后插入了數據,然后再指定某一個字段為主鍵時,必須要保證該字段數據不能重復
復合主鍵
在創建表的時候,在所有字段之后,使用primary key(主鍵字段列表)來創建主鍵,如果有多個字段作為主鍵,可以使用復合主鍵。
注意:一張表中只能有一個主鍵,但是不意味著,一個主鍵只能添加給一個字段。
id和course共同組成了一個主鍵。即,一個學生不能重復選同一門課程。
自增長
auto_increment:當對應的字段指定了auto_increment,插入數據的時候,該字段給值,則用該值;如果該字段不給值,會自動的被系統觸發,系統會從當前字段已經有的最大值+1,得到一個新的不同值,賦值給要插入數據的該字段。通常和主鍵搭配使用,作為邏輯主鍵。
如果建表的時候,不指定 auto_increment 的具體值,則從1開始。如果插入的數據被? auto_increment 指定的字段不給值,就從1自增。
如果插入的數據該字段有值,則使用該值。以后插入的數據,該字段如果不給值,則從該字段的最大值開始自增。
其實,插入一個數據的時候,表中就已經記錄了下次要插入的數據的該字段的值了。
唯一鍵
一張表中往往有很多字段需要唯一性,數據不能重復,但是一張表中只能有一個主鍵,此時,唯一鍵就可以解決表中有多個字段需要唯一性約束的問題。
唯一鍵的本質和主鍵產不多,唯一鍵允許字段為空,而且可以多個為空,空字段不做唯一性比較。
唯一鍵和主鍵的區別:
- 主鍵更多的是標識記錄的唯一性。
- 唯一鍵更多的是保證業務上,不要和別的信息出現重復。
假設一個場景比如在公司,我們需要一個員工管理系統,系統中有一個員工表,員工表中有兩列信息,一個身份證號碼,一個是員工工號,我們可以選擇身份號碼作為主鍵。而我們設計員工工號的時候,需要一種約束:而所有的員工工號都不能重復。具體指的是在公司的業務上不能重復,我們設計表的時候,需要這個約束,那么就可以將員工工號設計成為唯一鍵。一般而言,我們建議將主鍵設計成為和當前業務無關的字段,這樣,當業務調整的時候,我們可以盡量不會對主鍵做過大的調整。

外鍵
外鍵用于定義主表和從表之間的關系:外鍵約束主要定義在從表上,主表必須是有主鍵約束或unique唯一鍵約束的。當定義外鍵之后,要求外鍵列數據必須在主表的主鍵列存在或為null。
foreign key ( 字段名 ) references 主表 ( 列 )
案例:建立兩張表。我們來簡單實現學生的插入和班級的刪除,看看有什么問題。

- 建立學生表和班級表。
- 插入班級信息。
- 插入學生信息。
按照我們設計的學生表來看,插入“103王五3”是沒有問題的,但是不符合邏輯,因為班級表中,只有兩個班級,班級號分別為1,2,沒有班級號為3的班級,顯然這種設計是有問題的。也就是不能插入一個不存在的班級。
- 刪除班級信息。
如果刪除班級號1的班級,顯然也是不符合邏輯的,此時班級有學生,不能刪除班級。也就是不能刪除一個有學生的班級。
即,上面的設計是沒有約束的,會引發相關的不符合邏輯的問題。
此時,就引入了外鍵來解決上面的問題。學生依賴于班級,所以學生表為從表,班級表為主表。學生表中有班級號,班級表中也有班級號,所以班級號就可以作為關聯主表和從表的外鍵。
外鍵約束有兩個關鍵點:
- 從表和主表的關聯關系
- 產生外鍵約束
我們來重新設計表結構。
- 先建立主表班級表。
- 插入班級信息。
- 再建立從表學生表。
- 插入學生信息。
如果插入的學生信息,班級號在班級表中不存在,則報錯。即插入的班級一定是存在的。此時,外鍵班級號就讓從表和主表就有了關聯關系,同時產生了約束。
- 刪除班級信息。
如果刪除的班級還有學生,就報錯,不讓刪除,班級中沒有學生才能刪除。即刪除的班級一定是沒有學生的。此時,外鍵班級號就讓從表和主表有了關聯關系,同時產生了約束。
這就約束了,但凡插入表中的數據、刪除表中的數據的操作,一定是合法的符合邏輯的操作。
至此,本篇一共總結了八種約束。