資料庫進階二
阿新 • • 發佈:2020-08-06
一:約束條件
default 預設值
# 補充知識點 插入資料的時候 可以指定欄位順序 create table t1( id int, name char(16) ); insert into t1(name,id) values('jason',1); # 設定預設值 create table t2( id int, name char(16) not null, gender enum('male','female','others') default 'male' ); insert into t2(name,id) values('jason',1); insert into t2 values(2,'egon','female');
Unique 唯一
# 單列唯一 create table t3( id int unique, name char(16) ); insert into t3 values(1,'jason'),(1,'egon'); # 報錯 insert into t3 values(1,'jason'),(2,'egon'); # 正確 # 聯合唯一 ip 和 port 單個 都可以重複,但是 加在一起 必須是唯一的 create table t4( id int, ip char(16), port int, unique(ip,port) ); insert into t4 values(1,'127.0.0.1',8080); insert into t4 values(2,'127.0.0.1',8081); insert into t4 values(3,'127.0.0.2',8080); insert into t4 values(4,'127.0.0.1',8080); # 報錯
Primary Key 主鍵
1.單單從約束效果上來看 primary key = notnull + unique 非空 並且 唯一 create table t5(id int paimary key); insert into t5 values(null); # 報錯 insert into t5 values(1),(1); # 報錯 insert into t5 values(1),(2); # 正常 2.它除了有約束效果之外 它還是Innodb儲存引擎 組織資料的依據 Innodb儲存引擎在建立表的時候 必須有primary key 因為它類似於書的目錄 能夠幫助提高查詢效率 並且也是建表的依據 ① 一張表中 有且只有一個主鍵 如果沒有設定主鍵 那麼會從上往下搜尋 直到遇到一個 非空且唯一的欄位 將它自動生成主鍵 create table t6( id int, name char(16), age int not null unique, addr char(32) not null unique ); ② 如果表中沒有主鍵 也沒有其他任何的非空且唯一欄位 那麼Innodb會採用自己 內部提供的一個欄位 作為主鍵,隱藏 意味著你無法使用到它 就無法提升查詢速度 ③ 一張表中 通常都應該有一個主鍵欄位 並且通常將id/uid/sid欄位作為主鍵 # 單個欄位主鍵 create table t7( id int, name char(16) ); # 聯合主鍵(多個欄位聯合起來 作為表的主鍵 本質還是一個主鍵) create table t8( id int, ip char(16), port int, primary key(ip,port) ); 也就意味著 以後我們在建立表的時候 id欄位一定要加primary key
auto_increment 自增
# 當編號特別多的時候 人為地去維護太麻煩
create table t9(
id int primary key auto_increment,
name char(16)
);
insert into t9(name) values('jason');
insert into t9(name) values('egon');
insert into t9(name) values('tank');
# auto_increment只能加在主鍵上,不能給普通欄位加
create table t10(
id int primary key auto_increment,
name char(16),
cid int auto_increment
);
# 報錯:ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key
結論
以後再建立表的id(資料庫的唯一表示id、uid、sid)欄位的時候
id int primary key auto_increment
補充:
delete from 在刪除表中資料的時候 主鍵的自增不會停止
truncate t1 清空表資料 並且重置主鍵
二:約束--表與表之間建立關係
定義一張員工表 表中有很多欄位
id name gender dep_name dep_desc
# 1.該表的組織結構不是很清晰(可以忽視)
# 2.浪費硬碟空間(可忽視)
# 3.資料的擴充套件性極差(無法忽視的)
# 如何優化?
(上述問題類似於之前寫的python程式碼都在一個py檔案中)
將員工表拆分成 員工表 和 部門表
外來鍵
外來鍵 就是用來幫助我們建立 表與表之間關係的
foreign key
# 外來鍵帶來的約束
1.在建立表的時候 一定要先建立被關聯表
2.在插入資料的時候 也要先插入被關聯表
3.操作資料的時候 會出現多種限制:同步更新 同步刪除
表關係
表與表之間的關係最多隻有四種:
1.一對多關係
在MySQL的關係中 沒有多對一這個概念
一對多 多對一 都是 一對多
2.多對多關係
3.一對一關係
4.沒有關係
1.一對多關係
判斷 表與表之間關係的時候 前期不熟悉的情況下
一定要換位思考 分別站在2張表的角度考慮
以 員工表 與 部門表 為例
站在員工表:
1個員工能否對應多個部門(1條員工資料 能否對應多條部門資料)
不能!!!
(不能直接得出結論 一定發要2張表都考慮完全)
站在部門表:
1個部門能都對應多個員工(1個部門資料 能否對應多條員工資料)
能!!!
得出結論:
員工表 與 部門表 是單向的 一對多
所以 表關係 就是 一對多
SQL語句建表
# 1.一對多表關係 外來鍵欄位建立在多的一方
# 2.在建立表的時候 一定要先建被關聯表
# 3.在錄入資料的時候 也必須先錄入被關聯表
# 建立部門表
create table dep(
id int primary key auto_increment,
dep_name char(16),
dep_desc char(32)
);
# 建立員工表
create table emp(
id int primary key auto_increment,
name char(16),
gender enum('male','female','others') default 'male',
dep_id int,
foreign key(dep_id) references dep(id)
);
insert into emp(name,dep_id) values('xxq',1); # 報錯
insert into dep(dep_name,dep_desc) values('sb教學部','教書育人'),('外交部','多人外交'),('nb技術部','技術能力有限部');
insert into emp(name,dep_id) values('jason',2),('egon',1),('tank',1),('alex',3);
# 修改emp裡面的dep_id欄位 或者 dep表裡面的id欄位
update dep set id=200 where id=2; # 報錯
# 刪除dep表裡面的資料
delete from dep; # 報錯
# 1.先刪除教學部對應的員工資料 再刪除部門
操作太過繁瑣
# 2.真正做到資料之間有關係
更新 就同步更新
刪除 就同步刪除
級聯更新 級聯刪除
# 建立部門表
create table dep(
id int primary key auto_increment,
dep_name char(16),
dep_desc char(32)
);
# 建立員工表
create table emp(
id int primary key auto_increment,
name char(16),
gender enum('male','female','others') default 'male',
dep_id int,
foreign key(dep_id) references dep(id)
on update cascade # 同步更新
on delete cascade # 同步刪除
);
insert into dep(dep_name,dep_desc) values('sb教學部','教書育人'),('外交部','多人外交'),('nb技術部','技術能力有限部');
insert into emp(name,dep_id) values('jason',2),('egon',1),('tank',1),('alex',3);
update dep set id=200 where id=2; # 正常
delete from dep where id=1;
2.多對多關係
以 書本表 與 作者表 為例
站在書本表:
1本書能否對應多個作者(1條書本資料 能否對應多個作者資料)
能!!!
(不能直接得出結論 一定發要2張表都考慮完全)
站在作者表:
1本作者能否對應多本書(1條作者資料 能否對應多個書本資料)
能!!!
得出結論:
書本表 與 作者表 是雙向的 一對多
所以 表關係 就是 多對多
SQL語句建表
# 建立圖書表
create table book(
id int primary key auto_increment,
title varchar(32).
price int,
author_id int,
foreign key(author_id) references author(id)
on update cascade # 同步更新
on delete cascade # 同步刪除
);
# 建立作者表
create table author(
id int primary key auto_increment,
name varchar(32).
age int,
book_id int,
foreign key(book_id) references book(id)
on update cascade # 同步更新
on delete cascade # 同步刪除
);
按照上述的方式建立 一個都別想成功!!!
其實我們只是想記錄 書籍和作者的關係
!針對多對多欄位表關係 不能在2張原有的表中 建立外來鍵
需要你再單獨開設一張表 專門用來建立2張表之間的關係
# 建立圖書表
create table book(
id int primary key auto_increment,
title varchar(32),
price int
);
# 建立作者表
create table author(
id int primary key auto_increment,
name varchar(32),
age int
);
# 建立關聯表
create table book2author(
id int primary key auto_increment,
author_id int,
book_id int,
foreign key(author_id) references author(id)
on update cascade # 同步更新
on delete cascade, # 同步刪除
foreign key(book_id) references book(id)
on update cascade # 同步更新
on delete cascade # 同步刪除
);
3.一對一關係
id name age addr phone hobby email
如果一個表的欄位特別多 每次查詢又不是所有的欄位都能用到
將表一分為二:
使用者表資訊:
使用者表:
id name age
詳情表:
id addr phone hobby email
站在使用者表:
一個使用者能否對應多個使用者詳情 不能!!!
站在詳情表:
一個詳情能否屬於多個使用者 不能!!!
結論:單向的一對多 都不成立 那麼這個時候兩者之間的表關係
就是 一對一
或者 沒有關係(好判斷)
# 一對一 外來鍵欄位 建在任意一方都可以 推薦你建在查詢頻率比較高的表中
# 建立使用者詳情表
create table authordetail(
id int primary key auto_increment,
phone int,
address varchar(64)
);
# 建立使用者表
create table author(
id int primary key auto_increment,
name varchar(32),
age int,
address varchar(64),
authordetail_id int,
foreign key(authordetail_id) references authordetail(id)
on update cascade # 同步更新
on delete cascade # 同步刪除
);
總結
# 表關係的建立 需要用到 foreign key
一對多
外來鍵欄位 建立在多的一方
多對多
自己開設第三張表 儲存
一對一
建立在任意一方都可以 推薦建立在查詢評論高的表中
# 判斷表之間關係的方式:(換位思考!!!)
員工 與 部門
圖書 與 作者
作者 與 作者詳情
三:修改表的完整語法大全(瞭解)
# MySQL是不區分大小寫的
1.修改表名
alter table 表名 rename 新表名
2.增加欄位
alter table 表名 add 欄位名 欄位型別(寬度) 約束條件;
alter table 表名 add 欄位名 欄位型別(寬度) 約束條件 first; # 新增在最前面
alter table 表名 add 欄位名 欄位型別(寬度) 約束條件 after 欄位名; # 新增在欄位後面
3.刪除欄位
alter table 表名 drop 欄位名;
4.修改欄位
alter table 表名 modify 欄位名 欄位型別(寬度) 約束條件;
alter table 表名 chage 舊欄位名 新欄位名;
四:複製表(瞭解)
我們sql語句查詢的結果 其實也是一張虛擬表
create table 新表名 select * from 舊錶名; # 不能複製主鍵、外來鍵、索引 , 只能複製表結構和資料
create table 新表名 select * from 舊錶名 where id>3;