🍖表完整性約束詳解

引入

1.什麼是完整性約束, 爲何使用

爲了規範數據格式, 在用戶進行插入、修改、刪除等操做時,DBMS(數據庫管理系統(Data Base Management System))自動按照約束條件對數據進行監測, 使不符合規範的數據不能進入數據庫, 以確保數據的完整性和惟一性python

2.約束分類

表完整性約束條件與字段數據類型的寬度同樣, 都是可選參數,分爲如下幾種:mysql

完整性約束關鍵字 含義
NULL 標識字段值能夠爲空
NOT NULL 約束字段值不爲空
DEAFAULT 設置字段值爲默認值
UNIQUE KEY(UK) 約束字段的值惟一
PRIMARY KEY(PK) 設置字段爲表的主鍵
FOREIGN KEY(FK) 設置字段爲表的外鍵
AUTO_INCREAMENT 約束字段的值爲自動遞增
UNSIGNED 無符號
AEROFILL 使用 0 填充

一.null (空)

  • 被指定的字段的能夠爲空, 沒有指定則默認約束條件就是null
create table t04(id int); 
insert t04 value();      # values() 也能夠 value()
insert t04 value(null);  # 而且 into 能夠省略
insert t04 value(1);

image-20210131220611187

二.not null (非空)

  • 被指定字段的值不能爲空
create table t05(name char(16) not null);
insert t05 value();
insert t05 value(null);
insert t05 value("shawn");

image-20210131221836514

三.default (默認)

  • 被指定了default條件的字段在插入的值時, 不管null仍是not null均可以插入空
  • 插入時不給賦值默認填入default指定的默認值
  • 注意 : 當已經制定了約束條件not nulldefault後面就不能指定null做爲默認值
create table t06(name char not null default "shawn");
insert t06 value();
insert t06 value(null);

create table t07(name char not null dafault null);  # 直接報錯

image-20210131223045250

四.unique (惟一)

  • 被指定了unique的字段惟一, 兩種惟一 :
    1. 單列惟一 : 一個字段惟一
    2. 聯合惟一 : 多個字段聯合後惟一

1.單列惟一

create table t07(id int unique,name char(16));
insert t07 value(1,"shawn"),(2,"song");
insert t07 value(1,"xing");  # 報錯提示重複

image-20210131231603029

2.聯合惟一

create table t08(id int,ip varchar(16),port int,unique(ip,port));  # ip + port 聯合單個能夠重複, 聯合不能相同
insert t08 value(1,"127.0.0.1",8090);
insert t08 value(2,"127.0.0.1",8091);
insert t08 value(3,"127.0.0.1",8090);  # 聯合與id爲1的相同, 報錯

image-20210131234448702

3.not null + unique

  • 不爲空且惟一

五.primary key (主鍵)

主鍵約束(primary key)sql

1.什麼是主鍵約束

  • primary key 約束惟一表示數據庫表中的美條記錄
  • 主鍵列不能爲空(not null), 且必須惟一(unique), 效果上與(not null + unique同樣)
  • 每一個表都應該有一個主鍵, 而且每一個表只能有一個主鍵

2.主鍵的做用

  • ''索引''mysql提供的一種數據結構, 在mysql中稱之爲"鍵"
  • 它除了有約束效果以外, 它仍是Innodb存儲引擎組織數據的依據
  • 由於它相似於書的目錄, 可以提高查詢效率而且它也是建表的依據

3.未設置主鍵如何處理表

  • 首先Innodb從上往下搜索全部字段, 直到找到一個非空且惟一的字段, 該字段就會自動升級爲主鍵
  • 若是表中既沒有主鍵, 也沒有非空且惟一的字段, 那麼InnoDB會採用本身內部提供的一個隱藏字段做爲主鍵, 此時提高查詢效率的做用就沒法享受了(隱藏字段看不見)

ps : InnoDB引擎表是基於B+樹的索引組織表(IOT)(自行百度)數據庫

4.表的兩種主鍵方式

  • 單列主鍵 : 單個字段的主鍵
  • 聯合主鍵 : 多列作主鍵, 符合主鍵, 多個字段聯合作主鍵

5.驗證演示

  • 驗證約束效果 not null + unique (非空且惟一)
create table t09(id int primary key);  # 設置主鍵
insert t09 value(1),(2);
insert t09 value(null);  # 插入 null 報錯
insert t09 value(1);     # 插入id 1 報錯
insert t09 value(2);     # 插入id 2 也報錯

image-20210201093136789

  • 驗證不設置主鍵, 非空且惟一的字段自動升級主鍵
create table t10(
	id int not null unique,  # 設置 id 字段不爲空,且惟一
	name char(16) not null,
	age int,
	sex char(3) not null
);
desc t10;  # 查看錶結構

image-20210201093710163

  • 單列主鍵演示
create table t11(
    id int primary key,
    name varchar(16)
);
desc t11;

image-20210201094104260

  • 聯合主鍵演示
create table t12(
    ip varchar(16),
    port int,
    primary key(ip,port)  # 設置 IP + port 聯合主鍵
);
insert t12 value("127.0.0.1",8090);
insert t12 value("127.0.0.1",8091);  # 單個字段能夠相同
insert t12 value("127.0.0.1",8090);  # 連個字段不能相同, 報錯

image-20210201094548983

6.主鍵總結

  • 建表必須制定一個主鍵, 通常將 id 字段設置成主鍵
  • 制定主鍵字段後, 該字段就非空且惟一(Innodb引擎的查找機制就是非空且惟一字段)

六.auto_increment (自增加)

1.自增加說明

  • 自增加字段的值默認從 1 開始, 每次遞增 1
  • 自增加字段數據不能夠重複
  • 若是插入數據時id字段指定爲0null或未指定值,那麼就把這個表當前的AUTO_INCREMENT值填到自增字段
  • 若是插入數據時id字段指定了具體的值,就直接使用語句裏指定的值
  • 自增加字段必須是主鍵 (primary key)

2.使用場景

  • 編號過多, 人爲的去設置和維護太麻煩, 能夠添加自增字段解決

3.自增加演示

  • 不指定 id , 讓其自動增加
create table t13(
    id int primary key auto_increment,
    name varchar(16)
);
insert t13(name) value("shawn"),("xing");

image-20210201102712102

  • 指定 id, 則使用本身指定
insert t13 value(7,"xing"),(9,"hai");

image-20210201102923392

insert t13(name) value("hello");  # 再次不指定 id

image-20210201103115923

4.刪除表記錄和清空表的區別

  • 對於自增字段, 在用delete刪除後, 再插入值, 該字段仍按照刪除前的位置繼續增加(delete是一條一條刪除記錄)
🍓"delete"刪除表再插入記錄演示
delete from t13;
insert t13(name) value("shawn");

image-20210201104351135

  • 而使用truncate直接清空表, 不但將數據所有刪除, 並且從新定位自增的字段, 刪除大表時推薦使用
🍓"truncate"清空表再插入記錄演示
insert t13(name) value("song"),("hai"),("xing");  # 先插入幾條記錄
truncate t13;
insert t13(name) value("aaa"),("bbb"),("ccc");    # 再次插入記錄

image-20210201105044318

5.auto_increment修改和指定初始值

  • 修改初始值演示
alter table t13 auto_increment=18;
insert t13(name) value("ddd"),("eee"),("fff");
select * from t13;

image-20210201111652790

  • 建立表時指定初始值
create table t14(
    id int primary key auto_increment,
    name varchar(16),
    sex enum("male","female") default "male"
)auto_increment=5;  # 初始值的設置爲表選項,應該放到括號外
insert t14(name) value("aaa"),("bbb"),("ccc");

image-20210201113223103

七.foreign key (外鍵)

1.外鍵的做用

  • 可使得兩張表關聯, 保證數據一致性和實現級聯操做

2.外鍵介紹

  • 外鍵也稱之爲外鍵約束 : foreign key
  • MySQL 3.23.44版本後, Innodb引擎類型的表支持了外鍵約束
  • 外鍵 : 一張表的一個字段(非主鍵字段)指向零一個表的主鍵, 那麼該字段就稱之爲外鍵
  • 相關聯的兩張表必須是Innodb表, 目前只支持Innodb存儲引擎

3.子表和父表

  • 子表 : 外鍵所在的表稱之爲子表(附表)
  • 父表 : 外鍵所指向的主鍵所在的表稱之爲父表(主表)

image-20210201121839777

4.表的三種對應關係

  • 一對多(或者多對一)
  • 多對多關係
  • 一對一關係

ps : 得出表關係結論須要雙向進行觀察對比 (固然沒有關係也是一種關係數據結構

)測試

5.快速瞭解 foreign key 的使用

  • 咱們先定義一張員工表 : id、姓名、年齡、部門名、部門職能

image-20210201122939096

從上面的表中咱們不難發現缺點(以上只演示了7個員工, 假設有一萬個員工) :優化

  • 部門名和職能說明重複, 浪費磁盤空間
  • 組織結構不是很清晰
  • 數據的擴展性差 (重點)
  • 優化表的組織結構, 將其抽離成兩張表 : 員工信息表(emp)、部門表(dep)

image-20210201123958823

image-20210201124052479

表已經抽離成功, 咱們使用 dep_id 將兩個表創建聯繫設計

正常來講, 一個員工只能對應一個部門, 一個部門能夠包含多個員工code

結論 : 員工表與部門表是 一對多(或多對一) 的關係索引

  • 一對多關係表, 外鍵關鍵字設置在多的一方(emp)
  • 在建表時, 需先創建被關聯的表(主表)(dep), 否則先建立附表會報錯
  • 插入數據時, 必須先往被關聯的表(主表)插入(dep)
  • 演示操做

語法 : foreign key([子表字段]) references [主表名]([主表字段])

🍓先建立被關聯的表(主表)(dep)
create table dep(
    id int primary key auto_increment,
    dep_name varchar(16),
    dep_dec varchar(50)
);
insert dep(dep_name,dep_dec) value
    ("銷售部","銷售公司產品"),
    ("採購部","採購公司所需原材料"),
    ("售後部","爲客戶提供售後服務");  # 插入部門數據

🍓再建立附表(子表)(emp)
create table emp(
    id int primary key auto_increment,
    emp_name varchar(16),
    emp_age int,
    dep_id int,
    foreign key(dep_id) references dep(id)
);
insert emp(emp_name,emp_age,dep_id) value
    ("派大星",22,2),("章魚哥",32,2),
    ("蟹老闆",34,1),("海綿寶寶",23,3),
    ("珍妮",18,1),("痞老闆",54,3),
    ("珍珍",25,2);  # 插入員工數據

image-20210201133952835

image-20210201134125431

  • 相互關聯的主表和子表的關聯字段沒法更新, 除非設置級聯更新(下邊介紹)
update dep set id=100 where id=1;           # 報錯
update emp set dep_id=200 where dep_id=2;   # 報錯
  • 相互關聯的主表(dep)不能刪除記錄, 而子表(emp)能夠
delete from dep where id=2;  # 報錯
delete from emp where id=4;  # 能夠刪除成功

6.級聯更新與級聯刪除

  • 就是同步更新(on update cascade), 同步刪除(on delete cascade)
🍓新建一個子表,並設置級聯(emp2)
create table emp2(
    id int primary key auto_increment,
    emp2_name varchar(16),
    emp2_age int,
    dep_id int,
    foreign key(dep_id) references dep(id)
    on delete cascade
    on update cascade
);
insert emp2(emp2_name,emp2_age,dep_id) value
    ("派大星",22,2),("章魚哥",32,2),
    ("蟹老闆",34,1),("海綿寶寶",23,3),
    ("珍妮",18,1),("痞老闆",54,3),
    ("珍珍",25,2);  # 插入員工數據

image-20210201141033592

  • 更新(update)主表(dep)的 id, 子表(emp2)也隨之更新
drop table emp;  # 測試以前先刪除 emp 表,以避免受影響
update dep set id=100 where id=1;  # 將主表 id 爲 1 的改成 100

update emp2 set dep_id=300 where dep_id=3; # 子表沒法更新外鍵(報錯)

image-20210201141729175

  • 刪除(delete)主表的記錄, 子表中對應的記錄也隨之解散
delete from dep where id=100;  # 刪除 id 爲 100 的記錄(銷售部門)
select * from emp2;  # 查看 emp2 受到的影響

image-20210201142532380

7.如何找到兩張表之間的關係(訣竅)(分析步驟)

  • 步驟一 : 先站在左表的角度去找

是否左表的多條記錄能夠對應右表的一條記錄,若是是,則證實左表的一個字段能夠 foreign key 右表一個字段(一般是id)

  • 步驟二 : 再站在右表的角度去找

是否右表的多條記錄能夠對應左表的一條記錄,若是是,則證實右表的一個字段能夠 foreign key 左表一個字段(一般是id)

  • 結論 :

多對一 : 若是隻有步驟1成立,則是左表多對一右表, 若是隻有步驟2成立,則是右表多對一左表

多對多 : 若是步驟1和2同時成立,則證實這兩張表時一個雙向的多對一,即多對多,須要定義一個這兩張表的關係表(中間表)來專門存放兩者的關係

一對一 : 若是1和2都不成立,而是左表的一條記錄惟一對應右表的一條記錄,反之亦然, 這種狀況很簡單,就是在左表foreign key右表的基礎上,將左表的外鍵字段設置成unique便可

8.創建表之間的關係

  • 🔰多對一(或一對多) 關係創建
上面的"員工表(emp)"與"部門表(dep)"就是多對一的關係
  • 🔰多對多

場景演示 : 做者和書的對應關係

對應關係 : 一個做者能夠寫多本書, 一本書也能夠對應多個做者(合著) , 雙向的一對多,即多對多

關聯方式 : 設置外鍵(froeign key), 並使用一張中間表創建兩表的聯繫

image-20210201163050750

設計思路 : 建立一張中間表(au_bo), au_bo的一個id對應多個圖書表(book)的id, 也對應做者表(author)的多個id, 反過來則是多對一, 因而咱們就能夠在au_bo表內設置兩個外鍵foreign key 來分別關聯book表的idauthor表的id

🍓先建立"book"和"author"兩張表,並插入值
create table book(
    id int primary key auto_increment,
    title varchar(30) not null,
    price float(10,2) not null
);
insert book(title,price) value
    ("《蟹堡祕籍》",1000.5),("《菠蘿房建成手冊》",5000.25),
    ("《章魚哥做息日記》",2000),("《派大星哲學》",15000);

create table author(
    id int primary key auto_increment,
    name varchar(16) not null,
    age int not null
);
insert author(name,age) value("海綿寶寶",35),("派大星",34);

🍓再建立中間表"au_bo", 並設置外鍵創建聯繫
create table au_bo(
    id int primary key auto_increment,
    book_id int not null,
    author_id int not null,
    foreign key(book_id) references book(id)     # 設置外鍵
    on update cascade
    on delete cascade,  # 設置級聯更新和刪除
    foreign key(author_id) references author(id) # 設置外鍵
    on update cascade
    on delete cascade   # 設置級聯更新和刪除
);
insert au_bo(book_id,author_id) value(1,1),(1,2),(2,1),(3,1),(3,2),(4,2);
select * from book;
select * from author;
select * from au_bo;

image-20210201170019547

image-20210201170056743

image-20210201170222919

  • 🔰一對一

場景演示 : 一我的要去公司入職一個部門, 入職後就是員工, 部門對應的這我的是惟一的, 不可能有兩個如出一轍的人, 而這名員工對應的就這一個部門, 還好比一張身份證對應一我的

注意 : 必定得保證設置外鍵的字段惟一, 外鍵健在哪一方均可以, 建議建在查詢頻率較高的表中

🍓建立"people"表,並插入內容
create table card(
    id int primary key auto_increment,
    phone int not null,
    ID_card varchar(19) not null
);
insert card(phone,ID_card) value
    (458796,"3675454567855544555"),
    (784555,"3732458220113245979"),
    (458755,"2332214578621525545");

🍓建立"card"表,並插入內容
create table people(
    id int primary key auto_increment,
    name varchar(16) not null,
    sex enum("male","female") default "male",
    card_id int not null unique,
    foreign key(card_id) references card(id)
    on update cascade
    on delete cascade
);
insert people(name,sex,card_id) value
    ("shawn","male",1),
    ("song","female",2),
    ("xing","male",3);

select * from people;
select * from card;

image-20210201180142063

image-20210201180201125

---end---

相關文章
相關標籤/搜索