1. 程式人生 > 實用技巧 >資料庫進階二

資料庫進階二

一:約束條件

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;