數據庫 級聯 約束 外鍵
小練習:創建博客表
標題 發布時間 最后更新 作者 內容 字數
char(100) datetime timestamp char(100) longtext bigint
create table blog(
title char(100),
publish_time datetime,
last_update timestamp,
author char(100),
content longtext,
number bigint
);
insert into blog values(
"mysql 高級篇",
now(),
null,
"jerry 夫斯基",
"啥也不說了 就是很高級",
11);
select title from blog where number = 100;
上節課內容回顧
1.簡單的增刪改查語句
insert into table_name values(v1,v2,...);
insert into table_name(column1,column2) values(v1,v2,...);
insert into table_name values(v1,...) ,(v1,....);
delete from table_name where 條件;
update table_name set column = new_valuem,... where 條件;
select * from table_name;
select column1,... from table_name where 條件;
2.數據類型
1.整形
tyniint smallint mediumint int bigint
2.浮點
float double decimal
3.字符串
char varchar tiny | long [text blob] binary varbinary
枚舉 enum
集合 set
4.日期和時間
date time datetime year timestamp
什么是約束 constraint
約束就是一種限制,例如憲法,讓你不能做某些事情
數據庫的約束,是對數據的安全性,完整性的保證;
mysql中的約束
關鍵字 | 作用描述 | 舉例 |
---|---|---|
unique | 唯一性約束,表示這個字段不能出現重復的值, 用於唯一標識一條記錄 | 例如身份證號碼,學號等 |
not null | 非空約束,表示這個字段的值不能為空 | 例如姓名,密碼 |
null | 一些數據類型默認就是可以為空的 | |
default | 默認值,用於給某一個字段設置默認值 | gender enum("g","b") default "b" |
普通約束測試
#完整的建表語句
create table table_name(字段名稱 字段類型[(寬度) 約束]) charset 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");# ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'主鍵沖突;
insert into person values("2","jack"); # ok
insert into person values(null,"tom"); # Column 'id' cannot be null #主鍵不能為空
#從約束角度來看就等同於,非空+唯一
create table person2(
id char(19),
name char(20)
);
# 在innodb存儲引擎中 ,主鍵用於組織數據 (樹形結構)
# 也就說主鍵對於innodb引擎來說是必須要的,沒有不行!
# 如果沒有手動指定主鍵
# mysql 會自動查找一個具備非空且唯一的字段作為主鍵
# 如果也沒有也沒有這樣的字段,mysql會創建一個隱藏字段 作為主鍵
# 首先明確主鍵是一種索引 unique也是,索引的作用是加速查詢
# 如果我們在查詢語句中沒有使用索引字段 ,mysql將無法為我們的查詢加速 意味着如果沒有主鍵,將無法加速查詢
總的來說:主鍵 具備約束的作用,還能加快我們的查詢速度,所以今后在創建表的時候都應該創建索引字段
應該將什么樣的字段設置為主鍵????
如果本來的業務中就存在非空且唯一的字段 那就把它設為主鍵 如果沒有就自己添加一個字段專門作為主鍵
通常我們會將主鍵設置為類int 類型,是為了方便保證其唯一;
案例:
mysql> 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 teacher3(
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) references dept(id)
);
解釋:
foreign key(dept_id) references dept(id)
dept_id 表示當前表的外鍵字段
dept 表示要關聯哪個表
dept(id) id表示關聯的dept表的id字段
主表與從表
先有主表 再有從表
先有dept 再有teacher
foreign key 帶來的約束作用
1.在從表中插入一條記錄,關聯了一個主表中不存在的id 導致插入失敗
必須保證部門id (外鍵的值) 必須是在主表中存在的
2.插入數據的順序
先插入主表記錄 在插入從表記錄
3.從表更新外鍵時也必須保證 外鍵的值在主表中是存在的
4.刪除主表記錄前 要保證從表中沒有外鍵關聯被刪除的id
delete from dept where id = 1;# 報錯
必須先刪除從表 再刪除主表
delete from teacher where dept_id = 1;
delete from dept where id = 1;
5.更新主表記錄的主鍵時 要保證從表中沒有外鍵關聯被刪除的id
6.必須先創建主表
7.刪除表 必須先刪除從表
強調: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)
);
級聯操作 cascade
當我們需要刪除部門(主表)信息 時,必須先刪除從表中關聯的數據,很麻煩
級聯操作指的就是,當你操作主表時,自動的操作從表
兩種級聯操作
1.級聯的刪除
當刪除主表時自動刪除從表中相關數據
2.級聯更新
當主表的主鍵更新時自動的更新關聯的從表數據
案例:以上面的班級個學員為例:
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(10)
);
#老師表:
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),
);
多對多
如何確定多對多關系
例如 老師表 和 學生表
套路一樣 先站在老師表 在站在學生表
老師表角度: 一個老師可以對應多個學生 一對多
學生表角度: 一個學生可以對應多個老師 一對多
如果雙方都是一對多的關系 那么 兩者是多對多關系
處理方式2
建立一個中間表,用於存儲關系,至少具備兩個字段分別指向老師和學生的主鍵,兩個字段都是外鍵 如下:
create table t_s_r(
id int primary key auto_increment,
t_id int,
s_id int,
foreign key(t_id) references teacher(id),
foreign key(s_id) references 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(10));
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);
已知老師名稱為bgon 請找出他教過那些學生
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;
select * 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 s_id = 2;
3.通過老師的id取出老師的信息
select name from teacher where id = x;
# 子查詢方式:
select name from teacher where id = (
select t_id from t_s_r where s_id = (
select id from student where name = "老李"
)
);
一對一關系
如一個客戶對應一個學生:
站在兩邊看都是一對一的關系
處理方式三
確定先后順序
將先存在的數據作為主表
后存在的作為從表
使兩個表的id保持一一對應
方法1: 從表的id 即是主鍵又是外鍵
方法2:從表的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 在添加詳情表的數據
#將一條完整數拆分到不同表中,可以提高查詢的效率,上述方式稱之為垂直分表!
約束:
unique 唯一
not null 非空
null 可以為空
default 默認值
primary key 主鍵 ==(非空+唯一+加速查詢)
auto_increment 自動增長
foreign key 外鍵約束 , 保證兩張表的關系是完整的
級聯操作: 用在外鍵關聯中,可以級聯的刪除或更新從表記錄