目錄

前言

一、空屬性

二、默認值

三、列描述

四、zerofill

五、主鍵

六、自增長

七、唯一鍵

八、外鍵


前言

        本篇是mysql中表的相關約束部分!

真正約束字段的是數據類型,但是數據類型約束很單一,需要有一些額外的約束,更好的保證數據的合法性,從業務邏輯角度保證數據的正確性。這就是表的約束由來

表中一定要有各種的約束,通過約束讓我們未來插入數據庫表中的數據是符合預期的!!約束的本質是通過技術手段,倒逼程序員插入正確的數據,反之,站在mysql視角,凡是插進來的數據,都是符合數據約束的——約束的最終目標是保證數據的完整性和可預期性

一、空屬性

  • 兩個值:null(默認的)和not null(不為空)
  • 數據庫默認字段基本都是允許為空的,但在實際開發中我們要儘可能保證字段不為空,因為空值無法參與運算。

MySql 數據表約束_主鍵

如果要讓某個字段不允許為空,在創建表的時候就可以給對應字段設置 not null 屬性。

案例:創建一個班級表,包含班級名和班級所在的教室。

站在正常的業務邏輯中:

  • 如果班級沒有名字,你不知道你在哪個班級
  • 如果教室名字可以為空,就不知道在哪上課

所以我們在設計數據庫表的時候,一定要在表中進行限制,滿足上面條件的數據就不能插入到表中。這就是 “約束”。

create table if not exists myclass(
     class_name varchar(20) not null,
     class_room varchar(20) not null,
     other varchar(20)
);

MySql 數據表約束_字段_02

我們查看創建該表的詳細 SQL 語句:

MySql 數據表約束_字段_03

可以看到的是前兩個字段我們設置了not null,那麼在這裏就會顯示出來,表示我們是必須插入具體值得;而我們的這個other字段是沒有設置not null的,默認是 null 的,所以這裏後面跟的是default null,表示你想插就插,不插這一類就給默認值null。

我們可以做一下實驗驗證:

MySql 數據表約束_主鍵_04

所以説,如果某列設置了not null

  • 必須要插具體值
  • 不插因為後面沒有默認值就報錯
  • 插入null也報錯

如果設置為默認null,可以不插用的是後面帶的默認值。

二、默認值

默認值:某一種數據會經常性的出現某個具體的值,可以在一開始就指定好,在需要真實數據的時候,用户可以選擇性的使用默認值。

  • 如果某一個字段會經常性的出現某個值,那麼就可以考慮將這個值設置成該字段的默認值
  • 向表中插入數據時如果不給帶有默認值的字段賦值,那麼就會使用默認值進行插入

可以説默認值的目的就是為了可以簡化數據插入操作,提高數據一致性。

create table if not exists student(
     name varchar(12) not null,
     age tinyint unsigned default 20,
     gender varchar(10) default '男'
);

在此表中,age 默認值為20,gender默認值為“男”;當插入數據時,如未指定這些列的值,將使用默認值,如下:

MySql 數據表約束_數據_05

總結:default 和 not nul 並不衝突,而是互相補充的。

  • 當用户指明這一列要插的時候,受 null 和 not null 約束,要麼插null ,要麼插合法數據;總之用户指明這一列要插 ,not null 來約束
  • 當用户忽略這一列的時候,如果設置了默認值使用默認值,如果沒有就直接報錯;總之用户忽略這一列要插, default 來約束

MySql 數據表約束_字段_06

如果建表的時候, 不給某一列添加任何約束,我們會發現MySQL會對 sql語句 優化,默認會帶上default null。所以不插入的時候在表示會顯示null。

三、列描述

  • comment:用於給列添加註釋説明,便於程序員和數據庫管理員理解字段用途。
  • 該屬性不會對數據插入產生約束效果。
create table if not exists t10(
     name varchar(12) not null comment '用户的用户名',
     age tinyint unsigned default 20 comment '用户的年齡'
);

MySql 數據表約束_字段_07

可以得知的是通過desc查看不到註釋信息,但是通過show查看創建該表的詳細 SQL 語句時可以看到註釋信息

四、zerofill

  • zerofill:在數字前補零,使顯示字符長度符合指定的位數。
  • 數據庫存儲的 數值不變,僅用於展示效果。
create table if not exists t11(
    a int unsigned not null,
    b int unsigned zerofill not null
);

MySql 數據表約束_數據_08

這個 int(10) unsigned zerofill 的 10 意味着什麼呢?請看下圖

MySql 數據表約束_字段_09

 我們會發現,zerofill 還是挺形象的,格式就是填滿0,這就是zerofill屬性的作用,如果寬度小於設定的寬度(這裏設置的是10),自動填充0。要注意的是,這只是最後顯示的結果,在MySQL中實際存儲的還是1 ——如果以後你想顯示出的是001,002就可以設置zerofill(用來控制不夠的位數補全)。

這裏其實有個小細節,為什麼我們默認 int() 後面帶的是 10 ?更準確的是為什麼 unsigned int() 是10,int() 是11?


MySql 數據表約束_數據_10

 int佔4個字節,有符號取值範圍 -2^31 - 2^31-1,無符號取值範圍 2^32-1,無論是 2^31,還是 2^32 轉成10進制是21億多,42億多,這麼大的數字其實最後表示處理也就是10位,8位千萬,9位億,10位十億。用10就可以把所有整數數據位全都表示出來;而 int 多出一個1是因為它是有符號的,多一位標識符號位。

五、主鍵

主鍵:primary key用來唯一的約束該字段裏面的數據,不能重複,不能為空,一張表中最多隻能有一個主鍵;主鍵所在的列通常是整數類型

  • primary key:用於標識表中的唯一記錄,不允許重複或為空。
  • 表中最多隻能有一個主鍵列。
  • 主鍵可以通過複合主鍵的方式使用多列聯合唯一標識。
create table if not exists t12(
    id int unsigned primary key,
    name varchar(20) not null
);

在此示例中,id 被設為主鍵,數據庫自動為主鍵列添加 not null 約束。

MySql 數據表約束_字段_11

  • 主鍵約束對於程序員來講,未來想往這個表裏面插對應插入的數據主鍵列不能衝突,一旦衝突不讓你插入,所以倒逼程序員插的時候儘量不要出現主鍵衝突。
  • 其次站在 mysql視角 凡是插入這個表裏面的數據主鍵一定是不衝突的。這樣的好處是根據主鍵絕對能拿出來確定的一條記錄!——可以保證其唯一性
  • 有了主鍵可以有針對性的對數據進行增刪查改
    比如説更新:

創建主鍵有兩種方法:

  • 創建表的時候就把主鍵設置好
  • 表建好之和但沒有主鍵,可以追加主鍵

其次刪除 | 添加 主鍵的SQL 語句都是通過alter來進行的

MySql 數據表約束_數據_12

複合主鍵

  • 雖然一張表中最多隻能有一個主鍵,但是並不意味着一個表中的主鍵只能添加給一列!
  • 也就是説一個主鍵可以被添加到一列,或者多列上。
  • 一個主鍵被添加到多列上的數據我們就叫做複合主鍵

在創建表的時候,在所有字段之後,使用 primary key(主鍵字段列表) 來創建主鍵,如果有多個字段作為主鍵,可以使用複合主鍵。

下面我們就可以用兩列合起來當一個主鍵,如創建一張表讓一個學生不能選修同樣的課程

create table t13(
     id int unsigned,
     course_id int unsigned comment '課程編號',
     score tinyint unsigned comment '課程得分',
     primary key(id,course_id)
     );

MySql 數據表約束_主鍵_13

可以看到 id 和 course_id 都叫做主鍵。

因為一位同學可以選修多門課,而一門課又可以被多位同學選,所以我們把 學生id 和 課程id 合為一個主鍵,這就是複合主鍵的一個實際運用

MySql 數據表約束_數據_14

  • 換言之,可以選擇一列作為主鍵,也可以選擇多列作為主鍵
  • 但是多個合起來做一個主鍵,都不一樣可以插,有一個不一樣可以插,只有多個同時和歷史數據一樣才會出現主鍵衝突。 這就是複合主鍵。
  • 複合主鍵理解:將多列看成一個整體,全部同時衝突,才會約束
  • 後面可以支持通過主鍵進行快速查找。

六、自增長

auto_increment:當對應的字段,不給值,會自動的被系統觸發,系統會從當前字段中已經有的最大值+1操作,得到一個新的不同的值。通常和主鍵搭配使用,作為邏輯主鍵

就是字段自動增長,從當前最大值加 1,通常配合主鍵使用,確保值唯一。

  • 任何一個字段要做自增長,前提:本身是一個索引(key一欄有值)
  • 自增長字段必須是整數
  • 一張表最多隻能有一個自增長
create table t14(
    id int unsigned primary key auto_increment,
    name varchar(20) not null
);

MySql 數據表約束_主鍵_15

在此示例中,id 列自增長,無需顯式插入,系統自動為其賦值

MySql 數據表約束_數據_16

插入時,我們可以指定插入其他列,id這一列就不管了。可以看到雖然我並沒有告訴id要插什麼,但是id是自動幫我們插入的,並且是增長的。

和別人不衝突並且連續的,這就是自增長主鍵。

當我們指定id要插入的時候,也能插進行。然後再插入id相同值的時候,確實能夠履行主鍵的職責發生主鍵衝突。

自增主鍵的插入機制

  • 默認行為:自增主鍵在插入時若未設置任何默認值,則默認從1開始插入。
  • 手動設置起始值:如果手動插入一個新的起始值,且該值大於歷史值,則自增主鍵將從新的起始值開始進行插入。
  • 創建表時,除了在表內設置 auto_increment約束外 ,還可以在表外 設置auto_increment 的值,這代表下一次插入的起始值。
  • 可以使用 last_insert_id() 函數來獲取最後一次插入的 AUTO_INCREMENT 值(批量插入獲取的是第一個值 )
select last_insert_id();

MySql 數據表約束_主鍵_17

關於上面提及的索引:

在關係數據庫中,索引是一種單獨的、物理的對數據庫表中一列或多列的值進行排序的一種存儲結構,它是某個表中一列或若干列值的集合和相應的指向表中物理標識這些值的數據頁的邏輯指針清單。索引的作用相當於圖書的目錄,可以根據目錄中的頁碼快速找到所需的內容。

索引提供指向存儲在表的指定列中的數據值的指針,然後根據您指定的排序順序對這些指針排序。數據庫使用索引以找到特定值,然後順指針找到包含該值的行。這樣可以使對應於表的 SQL 語句執行得更快,可快速訪問數據庫表中的特定信息。

七、唯一鍵

 一張表中有往往有很多字段需要唯一性,數據不能重複,但是一張表中只能有一個主鍵:唯一鍵就可以解決表中有多個字段需要唯一性約束的問題

在一張表中,唯一鍵用於對多個需要唯一性約束的字段進行限制。雖然表中只能有一個主鍵,但可以使用多個唯一鍵來確保數據唯一性。

區別:

  • 主鍵:標識唯一性,主要用於唯一標識記錄。
  • 唯一鍵:更多地用於業務邏輯上的唯一性約束,允許字段為空,並且多個空值不會影響唯一性比較。

我們可以簡單理解成,主鍵更多的是標識唯一性的。而唯一鍵更多的是保證在業務上,不要和別的信息出現重複。乍一聽好像沒啥區別,我們舉一個例子

假設一個場景 (當然,具體可能並不是這樣,僅僅為了幫助大家理解)

比如在公司,我們需要一個員工管理系統,系統中有一個員工表,員工表中有兩列信息,一個身份證號碼,一個是員工工號,我們可以選擇身份號碼作為主鍵。

而我們設計員工工號的時候,需要一種約束:而所有的員工工號都不能重複。

具體指的是在公司的業務上不能重複,我們設計表的時候,需要這個約束,那麼就可以將員工工號設計成為唯一鍵。

一般而言,我們建議將主鍵設計成為和當前業務無關的字段,這樣,當業務調整的時候,我們可以儘量不會對主鍵做過大的調整。

當然,離我們近一些的例子就是:一個學生信息表中有學號,姓名和手機號三個字段,那麼我們設置學號為主鍵之後,這個手機號由於每個人都應該是不一樣的手機號,所以應該也給其設置一下唯一鍵

案例:

mysql> create table student (
    -> id char(10) unique comment '學號,不能重複,但可以為空',
    -> name varchar(10)
    -> );
mysql> insert into student(id, name) values('01', 'aaa');
mysql> insert into student(id, name) values('01', 'bbb'); -- 觸發唯一約束錯誤
ERROR 1062 (23000): Duplicate entry '01' for key 'id'
mysql> insert into student(id, name) values(null, 'bbb'); -- 允許為空

設置唯一鍵時加了一個unique來約束

MySql 數據表約束_字段_18

唯一鍵和主鍵不衝突,可以理解為對主鍵的補充設置,並且只能有一個主鍵,但可以有多個唯一鍵

八、外鍵

對於外鍵,我們主要理解兩個內容:

  • 從表和主表的關聯關係
  • 產生外鍵約束

外鍵用於確保表間數據的一致性,例如防止插入一個不存在班級的學生或刪除一個還有學生的班級。

  • 定義:外鍵約束用於建立主表和從表之間的關聯關係,主要定義在從表上,主表必須包含主鍵或唯一鍵。

外鍵用於定義主表和從表之間的關係:

  • 外鍵約束主要定義在從表上
  • 主表則必須是有主鍵約束或unique約束
  • 當定義外鍵後,要求外鍵列數據必須在主表的主鍵列存在或為NULL

設置外鍵約束SQL語句:

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

案例:

-- 主鍵表:班級表
create table class (
    id int primary key,
    name varchar(30) not null comment '班級名'
);
-- 從表:學生表
create table stu (
    id int primary key,
    name varchar(30) not null comment '學生名',
    class_id int,
    foreign key (class_id) references class(id)
);
-- 插入班級數據
mysql> insert into class values(10, '高三(9)班'),(20, '高三(19)班');
-- 插入學生數據
mysql> insert into stu values(100, '張三', 10), (101, '李四', 20);
-- 插入無效班級號的數據,觸發外鍵約束錯誤
mysql> insert into stu values(102, '王五', 30); -- 無效插入

MySql 數據表約束_主鍵_19

[^]: 可以看到,並不存在 id為3的班級

可以這麼理解外鍵約束:通過外鍵約束將表間關係交由數據庫管理,避免在業務上關聯的表間出現不一致的數據。

MySql 數據表約束_數據_20