約束
約束就是一種限制,規定不能做某些事情
數據庫的約束,是對數據的安全性,完整性的保證
mysql中的約束
unique
唯一性約束,表示這個字段不能出現重復的值,用於唯一標識一條記錄
比如身份證號碼,學號等
not null
非空約束,表示這個字段的值不能為空
比如賬號,密碼
null
一些數據類型默認就是可以為空的
default
默認值,用於給某一個字段設置默認值
普通約束測試
#完整的建表語句
create table table_name(字段名稱 字段類型[(寬度)約束]) charest utf8;
#學生表具備 姓名 性別 學號
create table student(
#非空
name char(20) not null,
#默認值
gender enum('g','b') default 'b',
#唯一
id int unique
)
#測試
insert into student values(null,null,null);#錯誤原因是 name不能為空
insert into student values('jack',null,null);#可以插入,null也是一個特殊的值,並且id的唯一約束,也可以為null
insert into student(name,id) values('jack',null);#可以插入,當沒有給gender指定參數時,將使用默認值
alter table student modify id int unique not null;#為已經存在的字段添加約束
primary key
主鍵約束,從約束角度來看就等同於,非空+唯一
主鍵與普通的約束的區別:
create table person(
id char(19) primary key,
name char(20)
);
insert into person values('1','rose');#ok
insert into person values('1','jack');#主鍵唯一,不能為'1',報錯
insert into person values('2','jack');#ok
insert into person values(null,'tom');#主鍵不能為空,報錯
#從約束角度來看就等同於,非空+唯一
create table person2(
id char(19),
name char(20)
);
#在innodb存儲引擎中,主鍵用於組織數據(樹形結構)
#也就是說對於主鍵對於innodb引擎來說是必須要的,沒有不行!
#如果沒有手動指定主鍵,mysql會自動查找一個具備非空且唯一的字段作為主鍵
#如果也沒有這樣的字段,mysql會創建一個隱藏字段,作為主鍵
#首先明確主鍵是一種索引,unique也是,索引的作用是加速查詢
#如果我們在查詢語句中沒有使用索引字段,mysql將無法為我們加速查詢,意味着如果沒有主鍵,將無法加速查詢
總的來說,主鍵具有約束的作用,還能加快查詢速度,所以在創建表的時候應該創建一個索引字段;
如果本來業務中就存在一個非空且唯一的字段,那就把它設置為主鍵,如果沒有那就自己添加一個字段專門作為主鍵,通常將主鍵設置為int類型,是為了方便保證其唯一。
案例:
create table PC(
id int primary key,
pp char(20),
model char(10),
price float
);
mysql> insert into PC values(1,"IBM","1214SB",40000);
mysql> insert into PC values(2,"DELL","1200DSB",4000);
mysql> select *from PC;
mysql> select *from PC where id = 1;
mysql> select *from PC where pp = "DELL";
為主鍵設置自動增長
當我們創建了主鍵字段時,插入數據必須保證主鍵是唯一的不能重復,這就需要我們自己管理主鍵值,這是很麻煩的,所以mysql有一個自動增長的屬性,可以添加在整形字段上,每次插入數據時,都可以自動的插入值,並且每次加1不會沖突;
create table teacher(
id int primary key auto_increment,
name char(10)
);
insert into teacher values(null,'jack');#對於自動增長得字段可以給null,也會自動生成值
insert into teacher(name) values('jack');#也可以跳過這個字段
create table teacher(
id char unique auto_increment,
name char(10)
);
自動增長可以用在具備索引,並且是數字類型的字段上,但是通常與主鍵一起使用
表之間的關系
foreign key
外鍵約束,用於指向另一個表的主鍵字段
#創建表的時候添加外鍵
create table teacher(
id int primary key auto_increment,
name char(20),
gender char(1),
dept_id int,
foreign key(dept_id) regerences dept(id)
);
解釋:
foreign key(dept_id) references dept(id)
dept_id表示當前表的外鍵字段
dept 表示要關聯哪個表
dept(id) id表示關聯的的普通表的id字段
主表與從表
先有主表 再有從表
先有dept 再有teacher
foreign key 帶來的約束作用:
-
在從表中插入一條記錄,關聯了一個主表中不存在的id, 會導致插入失敗
必須保證部門id(外鍵的值)必須是在主表中存在的
-
插入數據的順序
現插入主表記錄,再插入從表記錄
-
從表更新外鍵時也必須保證 外鍵的值在主表中是存在的
-
刪除主記錄前,要保證從表中沒有外鍵關聯被刪除的id
delete from dept where id=1;#報錯 #必須先刪除從表,再刪除主表 delete from teacher where dept_id=1; delete from dept where id=1;
-
更新主表記錄的主鍵時,要保證從表中沒有外鍵關聯被刪除的id
-
必須先創建主表
-
刪除表必須先刪除從表
強調:foreign key就是用來保證兩張表之間的關聯是正確的
練習:班級表和學員表
主表是班級
從表是學員 外鍵加給學員
create table class(
id int primary key auto_increment,
name char(20)
);
create table student(
id int primary key auto_increment,
name char(20),
gender char(1),
c_id int,
foreign key(c_id) references class(id)
);
級聯操作
當我們需要刪除主表的信息時,必須先刪除從表中關聯的數據,很麻煩
級聯操作指的就是,當操作主表時,自動的操作從表
兩種級聯操作
-
級聯的刪除
當刪除主表時自動刪除從表中的相關數據
-
級聯更新
當主表的主鍵更新時自動更新的更新關聯的從表數據
案例:
drop table if exists class;
# 如果這表存在 才執行刪除 可以避免報錯 if exists
# if not exists 如果不存在才執行
create table class(
id int primary key auto_increment,
name char(20)
);
insert into class values(null,"py9");
insert into class values(null,"py10");
#創建表的時候指定級聯操作
drop table if exists student;
create table student(
id int primary key auto_increment,
name char(20),
gender char(1),
c_id int,
foreign key(c_id) references class(id)
on update cascade
on delete cascade
);
# 級聯操作可以單獨使用 也可以一起使用 空格隔開即可
insert into student values(null,"jack","m",1);
insert into student values(null,"rose","m",1);
insert into student values(null,"tom","m",2);
外鍵的使用
什么時候使用外鍵:
表之間存在關聯關系:
多對一(一對多)
老師和部門的關系
老師的角度看
一個老師應該對應有一個部門
一個老師可以對應對多個部門? 不行 一個老師只能屬於一個部門 (要看具體業務要求)!
多個老師可以對應一個部門
多對一
部門的角度看
一個部門可以對應多個老師
一個部門可以對應一個老師
多個部門可以對應一個老師? 不行
一對多
如何處理一對多(多對一)?
在老師表中存儲 部門id
即多的一方存儲 一的一方的id
處理方式
在一的一方即teacher表中保存相應的部門(多的一方)的編號;
案例:
#部門
create table dept(
id int primary key auto_increment,
name char(20),
job char(50),
manager char(19),
);
#老師表
create table teacher(
id int primary key auto_increment,
name char(20),
gender char(1),
dept_id int,
foreign key(t_id) references teacher(id),
);
多對多
如何確定多對多關系
例如:老師表和學生表
老師表角度:一個老師可以對應多個學生 一對多
學生表角度:一個學生可以對應多個老師 一對多
如果雙方都是一對多的,那么兩者都是多對多關系
處理方式
建立一個中間表,用於存儲關系,至少具備兩個字段分別指向老師和學生的主鍵,兩個字段都是外鍵,如下:
create table t_s_r(
id int primary key auto_increment,
t_id int,
s_id int,
foreign key(t_id) reference teacher(id),
foreign key(s_id) regerence student(id),
unique key(t_id,s_id)
);
上表中id是可選的,問題是如何保證沒有重復干關系?
方式1:
給兩個字段設置為唯一+非空
#假設表已經存在了
alter table t_s_r add unique key(t_id,s_id);
#創建表時指定,多字段聯合唯一
create table t_s_r2(t_id int,s_id int,unique key(t_id,s_id));
方式2:
#推薦 將中間的關系表 兩個id 作為聯合主鍵 同時具備了 唯一且非空約束
create table t_s_r3(t_id int ,s_id int,primary key(t_id,s_id));
處理多對多關系:
1. 創建兩個主表 如學生和老師
2. 創建關系表 包含兩個字段 分別設置外鍵 指向對應的表
3. 將兩個字段 作為聯合外鍵
案例
create table student(id int primary key auto_increment,name char(19));
create table teacher(id int primary key auto_increment,name char(10));
create table t_s_r(
t_id int ,
s_id int ,
foreign key(t_id) references teacher(id),
foreign key(s_id) references student(id),
primary key(t_id,s_id)
);
#先插入 學生表或者老師表都可以 但是關系表一定是最后添加的
insert into teacher values(null,'bgon'),(null,'nike')
insert into student values(null,'老王'),(null,'老李')
#老王被bgon教過
insert into t_s_r values(1,1)
#nike教過老李
insert into t_s_r values(2,2)
#nike教過老王
insert into t_s_r values(2,1)
已知老師名為egon 請找出他教過的學生
1. 通過名字獲取 bgon的id
2. 拿着id取關系表中拿到一堆學生的id
3. 通過學生的id取出學生的信息
select id from teacher where name='bgon';
select s_id from t_s_r where t_id=1;
selsct * from student where id=1;
#子查詢方式 把一條語句的結果作為另一條語句的條件
select * from student where id=(select s_id from t_s_r where t_id=(select id from teacher where name='bgon'));
已知學生名為老李 請查詢出 哪些老師教過他
1.通過名字獲取老李id
select id from student where name='老李';
2.拿着id去關系表,找到老師id
select t_id from t_s_r where t_id=2;
3.通過老師的id取出老師的信息
select * from teacher where id=x;
#子查詢方式
select name form teacher where id=(select t_id form t_s_r where s_id=(select id from student where name='老李'))
一對一關系
如一個身份證對應一個公民
粘在兩邊都是一對一的關系
處理方式:
確定先后順序,將先存在的數據作為主表,后存在的作為從表
使兩個表的id保持一一對應
方法一:從表的id 即是主表又是外鍵
方法二:從表的id設置為外鍵,並保證唯一
案例:
#人員表
create table person(
id int primary key auto_increment,
name char(10),
age int
);
#詳情表
create table person_info(
id int primary key,
height float,
weight float,
foreign key(id) references person(id)
);
#在這樣的關系中 必須先插入主表即person 拿到一個id 在添加詳情表的數據
#將一條完整數據拆分到不同表中,可以提高查詢效率,上述方法稱之為垂直分表