數據庫 級聯,約束,外鍵


數據庫 級聯 約束 外鍵

小練習:創建博客表

標題 發布時間 最后更新 作者 內容 字數

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);

外鍵的使用

什么時候使用外鍵:
​表之間存在關聯關系 ,
首先要確定表之間的關系:

多對一

​一對多(多對一)

1562916076988
或者

1562916076988

老師和部門的關系
老師的角度看
一個老師應該對應有一個部門
一個老師可以對應對多個部門?  不行 一個老師只能屬於一個部門 (要看具體業務要求)!
多個老師可以對應一個部門
多對一
部門的角度看
一個部門可以對應多個老師
一個部門可以對應一個老師
多個部門可以對應一個老師? 不行
一對多
如何處理一對多(多對一)?
在老師表中存儲 部門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.將兩個字段 作為聯合主鍵  

案例

1562916076988

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    外鍵約束 , 保證兩張表的關系是完整的
​級聯操作: 用在外鍵關聯中,可以級聯的刪除或更新從表記錄  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM