1. 程式人生 > 實用技巧 >Crunching Numbers with AVX and AVX2

Crunching Numbers with AVX and AVX2

MySQL資料管理

目錄

1. 外來鍵(瞭解)

1. 方式1

在建立表的時候,增加約束(麻煩,比較複雜)

create table `grade` (
  `gradeId` int(10) not null auto_increment comment '年級id',
  `gradename` varchar(50) not null comment '年級名稱',
  primary key (`gradeId`)
)engine=innodb default charset=utf8

drop table if exists student

/*學生表的gradeId欄位要去引用年級表的gradeId
  定義外來鍵key
  給這個外來鍵新增約束(執行引用)
  fk = foreign key的簡寫
 */
create table if not exists `student` (
  `id` int (4) not null auto_increment comment '學號',
  `name` varchar (30) not null default '匿名' comment '姓名',
  `pwd` varchar (20) not null default '123456' comment '密碼',
  `sex` varchar (2) not null default '女' comment '性別',
  `birthdat` datetime default null comment '出生日期',
  `gradeId` int(10) not null comment '學生的年級',
  `address` varchar (100) default null comment '家庭住址',
  `email` varchar (50) default null comment '郵箱',
  primary key (`id`),
  key `fk_gradeId` (`gradeId`),
  constraint `fk_gradeId` foreign key (`gradeId`) references `grade` (`gradeId`) 
) engine innodb default charset = utf8 

刪除有外來鍵關係的表的時候,必須先刪除應用別人的表(從表),再刪除被應用的表(主表)

2. 方式2

建立表成功後,新增外來鍵約束

/*建立表的時候,沒有外來鍵關係
  alter table 表名
  add constraint 約束名 foreign key(作為外來鍵的列) references 引用到的表(引用到的表中的對應的列);
*/
create table if not exists `student` (
  `id` int (4) not null auto_increment comment '學號',
  `name` varchar (30) not null default '匿名' comment '姓名',
  `pwd` varchar (20) not null default '123456' comment '密碼',
  `sex` varchar (2) not null default '女' comment '性別',
  `birthdat` datetime default null comment '出生日期',
  `gradeId` int(10) not null comment '學生的年級',
  `address` varchar (100) default null comment '家庭住址',
  `email` varchar (50) default null comment '郵箱',
  primary key (`id`)
) engine innodb default charset = utf8 

alter table `student`
add constraint `fk_gradeId` foreign key(`gradeId`) references `grade`(`gradeId`);

以上的操作都是物理外來鍵,資料庫級別的外來鍵,不建議使用!(避免資料庫過多造成困擾,這裡瞭解即可)

最佳實現

  • 資料庫就是單純的表,只用來存資料,只有行(資料)和列(欄位)

  • 我們想使用多張表的資料,想使用外來鍵(程式去實現)

2. DML語言(全部記住)

資料庫意義:資料儲存,資料管理

DML語言:資料操作語言

  • insert
  • update
  • delete

1. 新增

insert

/*插入語句(新增)
insert into 表名([欄位1,欄位2,欄位3])values('值1'),('值2'),('值3'),......
*/
insert into `grade`(`gradename`) values('大四')

/*由於主鍵自增,我們可以省略主鍵
  如果不寫表的欄位,它就會一一匹配
  一般寫插入語句,我們一定要資料和欄位一一對應
*/

/*插入多個欄位
  values後面的欄位用()包裹,並用,隔開
*/
insert into `grade`(`gradename`) 
values('大二'),('大一')

insert into `student`(`name`) values('張三')

insert into `student`(`name`,`pwd`,`sex`) values('張三','aaaaaa','男')

insert into `student`(`name`,`pwd`,`sex`) 
values('李四','bbbbbb','男'),('王五','cccccc','男')

語法

insert into 表名([欄位1,欄位2,欄位3])values('值1'),('值2'),('值3'),......

注意事項

  1. 欄位和欄位之間使用英文逗號隔開
  2. 欄位是可以省略的,但是後面的值必須一一對應,不能少
  3. 可以同時插入多條資料,values後面的值需要使用(),(),...隔開

2. 修改

update

/*修改學生的名字
*/
update `student` set `name`='wang' where id = 1
/*不指定條件的情況下,會改動所有表!
*/
update `student` set `name`='wang'
/*修改多個屬性,用逗號隔開*/
update `student` set `name` = 'wang', `email` = '[email protected]' where id = 1
/*通過多個條件,定位資料*/
update `student` set `name` = '這是一個名字' where `name` = 'wang' or `sex` = '女'

語法

update 表名 set column_name = value, [column_name = value,...] where [條件]		--column列欄位

條件:where子句 運算子

操作符 含義 範圍 結果
= 等於 5=6 false
<>或!= 不等於 5<>6 true
> 大於 5>6 false
< 小於 5<6 true
<= 小於等於 5<=6 true
>= 大於等於 5>=6 false
between...and... 在某個範圍內,閉合區間 [2,5]
and &&和 5>1 and 1>2 false
or ||或 5>1 or 1>2 true

注意:

  • column_name 是資料庫的列,儘量帶上``
  • 條件,篩選的條件,如果沒有指定,則會修改所有的列
  • value可以是一個具體的值,也可以是一個變數

3. 刪除

1. delete命令

語法

delete from 表名 [where 條件]

/*刪除資料(避免這樣寫,會全部刪除)*/
delete from `student`

/*刪除指定資料*/
delete from `student` where id = 1

2. truncate命令

作用:完全清空一個數據庫表,表的索引和約束條件不會變!

/*清空student表*/
truncate `student`

3. delete和truncate的區別

  • 相同點:都能刪除資料,都不會刪除表結構
  • 不同點:
    • truncate 能重新設定自增列,計數器會歸零
    • truncate 不會影響事務

4. delete刪除的問題

重啟資料庫,現象:

  • INNODB:自增列會從1開始(資料存在記憶體當中,斷電即失)
  • MYISAM:繼續從上一個自增量開始(資料存在檔案中,不會丟失)

3. DQL語言(最重點)

查詢資料

1.DQL

Data Query Language:資料查詢語言

  • 所有的查詢操作都用它 Select
  • 簡單的查詢,複雜的查詢它都能做
  • 資料庫最核心的語言,最重要的語句
  • 使用頻率最高的語言

select完整的語法

select [all | distinct]
{* | table.* | [table.field1[as alias1][,table.field2[as alias]][,...]]}
from table_name [as table_alias]
	[left | right | inner join table_name2]	-- 聯合查詢
	[where ...]	-- 等值查詢,指定結果需要滿足的條件
	[group by ...]	-- 指定結果按照哪幾個欄位來分組
	[having]	-- 過濾分組的記錄必須滿足的次要條件
	[order by ...]	-- 排序,指定查詢記錄按照一個或者多個條件排序
	[limit {[offset,]row_count | row_countoffset offsets}];	-- 分頁,指定查詢的記錄從哪條至哪條

注意:[ ]代表可選的,{ }代表必選的

2. 指定查詢欄位

-- 查詢全部的學生  select 欄位 from 表名
select * from `student`

-- 查詢指定欄位
select `studentno`, `studentname` from `student`

-- 別名,給結果起一個名字  as
-- 可以給欄位起別名,也可以給表起別名
select `studentno` as 學號, `studentname` as 學生姓名 from `student` as s

-- 函式 concat(a,b)
-- 作用:將多個字串合連線為一個字串
select concat ('姓名:',`studentname`) as 新名字 from `student`

語法

select 欄位1,... from 表

有的時候,列的名字不是那麼的見名知意,此時我們可以起別名 用as

欄位名 as 別名 
表名 as 別名

1. 去重

-- 查詢一下有哪些同學參加了考試(有成績)
select * from `result`	-- 查詢全部的考試成績
-- 查詢有哪些同學參加了考試
select `studentno` from `result`
-- 發現重複資料,去重
select distinct `studentno` from `result`

作用:去除select查詢出來的結果中重複的資料,重複的資料只顯示一條

2. 資料庫的列(表示式)

-- 查詢系統版本(函式)
select version()
-- 用來計算(表示式)
select 100*3-1 as 計算結果
-- 查詢自增的步長(變數)
select @@auto_increment_increment

-- 學生考試成績+1分檢視
select `studentno`,`studentresult`+1 as 提分後 from result

資料庫中的表示式:文字值,列,Null,函式,計算表示式,系統變數...

語法

select 表示式 from 表

3. where條件子句

作用:檢索資料中符合條件的值

搜尋的條件由一個或多個表示式組成,返回結果為布林值

1. 邏輯運算子

運算子 語法 結果描述
and && a and b a&&b 邏輯與
or || a or b a||b 邏輯或
not ! not a !a 邏輯非

儘量使用英文字母

-- ==================  where ===================
select `studentno`,`studentresult` from result

-- 查詢考試成績在95~100分之間的
select `studentno`,`studentresult` from result
where `studentresult` >=95 and `studentresult` <=100

-- 模糊查詢(區間)
select `studentno`,`studentresult` from result
where `studentresult` between 95 and 100

-- 除了1000號學生之外的同學的成績 not !
-- 注意not的位置!
-- 不加not:where `studentno`=1000,因此not放在 where之後對取值取非
select `studentno`,`studentresult` from result
where not `studentno`=1000

select `studentno`,`studentresult` from result
where `studentno` != 1000

2. 模糊查詢

比較運算子

運算子 語法 描述
is null a is null 如果操作符為null,則結果為true
is not null a is not null 如果操作符為not null,則結果為true
between...and... a between b and c 若a在b和c之間,則結果為true
like a like b SQL匹配,如果a匹配b,則結果為true(可以使用萬用字元)
in a in (a1,a2,a3,...) 假設a在a1,或者a2...其中的某一個值中,結果為true(不能使用萬用字元)
-- ==================  模糊查詢  ===================

-- ==================  like  ===================
-- 查詢姓張的同學
-- like結合 %(代表0到任意個字元) _(一個字元)
select `studentno`,`studentname` from `student`
where `studentname` like '張%'

-- 查詢姓張的同學,名字後面只有一個字的
select `studentno`,`studentname` from `student`
where `studentname` like '張_'

-- 查詢姓張的同學,名字後面只有兩個個字的
select `studentno`,`studentname` from `student`
where `studentname` like '張__'

-- 查詢名字中有偉的同學 %偉%
select `studentno`,`studentname` from `student`
where `studentname` like '%偉%'

-- ==================  in  ===================
-- in是具體的一個或多個值,不可以用萬用字元
-- 查詢1000,1001號學員資訊
select `studentno`,`studentname` from `student`
where `studentno` in (1000,1001)

-- 查詢在北京的學生
select `studentno`,`studentname` from `student`
where `address` in ('北京朝陽')

-- ==================  null	not null  ===================
-- 查詢地址為空的學生 null或者''
select `studentno`,`studentname` from `student`
where `address`='' or `address` is null

-- 查詢有出生日期的同學=不為空
select `studentno`,`studentname` from `student`
where `borndate` is not null

-- 查詢沒有出生日期的同學=為空
select `studentno`,`studentname` from `student`
where `borndate` is null

4. 聯表查詢

1. join對比

-- ==================  聯表查詢 join  ===================
-- 查詢參加了考試的同學(學號,學號,科目編號,分數)
select * from student
select * from result

/*思路
1.分析需求,分析查詢的欄位來自哪些表(超過一張表採用連線查詢)
2.確定使用哪種連線查詢?
  確定交叉點(這兩個表中哪個資料是相同的)
 判斷的條件:學生表中的studentno = 成績表studentno
 表的別名.欄位:表示要查詢的欄位來源於哪個表
 */
 
select s.`studentno`,`studentname`,`subjectno`,`studentresult`
from `student` as s
inner join `result` as r
on s.`studentno` = r.`studentno`
 
-- Right Join
select s.`studentno`,`studentname`,`subjectno`,`studentresult`
from `student` as s
right join `result` as r
on s.`studentno` = r.`studentno`

-- Left Join
select s.`studentno`,`studentname`,`subjectno`,`studentresult`
from `student` as s
left join `result` as r
on s.`studentno` = r.`studentno`

-- 查詢缺考的同學
select s.`studentno`,`studentname`,`subjectno`,`studentresult`
from `student` as s
left join `result` as r
on s.`studentno` = r.`studentno`
where `studentresult` is null
操作 描述
inner join 如果表中至少有一個匹配,就返回行
left join 會從左表中返回所有的值,即使右表中沒有匹配
right join 會從右表中返回所有的值,即使左表中沒有匹配

join on 和where

join (連線的表) on (判斷的條件)	連線查詢(多張表)

where 等值查詢(一張表)

查詢多張表

-- 查詢了參加考試的同學資訊:學號,學生姓名,科目名稱,分數
/*思路
1.分析需求,分析查詢的欄位來自哪些表:student,result,subject
2.確定使用哪種連線查詢?
  確定交叉點(這兩個表中哪個資料是相同的)
  左表為學生表,右表為成績表時,使用右連,這樣可以將所有參加了考試的學生number輸出
  on條件為學號相等,即可篩選出參加了考試的學生
  查詢科目,將結果表與科目表inner join,on的條件為相同的subjectno,這樣就能查出對應的subjectname
 判斷的條件:學生表中的studentno = 成績表studentno
 表的別名.欄位:表示要查詢的欄位來源於哪個表
 */
 select s.`studentno`,`studentname`,`subjectname`,`studentresult`
 from `student` as s
 right join `result` as r
 on r.`studentno`=s.`studentno`
 inner join `subject` as sub
 on sub.`subjectno`=r.`subjectno`
 
 /*
我要查詢哪些資料  select ...
從哪幾個表中查  from 表 XXX join 連線的報表 on 交叉條件
假設存在多張表查詢,慢慢來,先查詢兩張表然後再慢慢增加
a left join b on XXX	:以a表位基準(左連線)
a right join b on XXX	:以b表位基準(右連線)
*/

2. 自連線

自己的表和自己的表連線,核心:一張表拆為兩張一樣的表即可

父類

categoryId categoryName
2 資訊科技
3 軟體開發
5 美術設計

子類

pid categoryId categoryName
3 4 資料庫
2 8 辦公技術
3 6 web開發
5 7 ps技術

操作:查詢父類對應的子類關係

父類 子類
資訊科技 辦公資訊
軟體開發 資料庫
軟體開發 web開發
美術設計 ps技術
-- 查詢父子資訊
select a.`categoryname` as '父欄目',b.`categoryname` as '子欄目'
-- 將一張表看為兩個一模一樣的表
from `category` as a,`category` as b
where a.`categoryid`=b.`pid`

5. 分頁和排序

1. 排序

-- ================  排序 order by  ===============
-- 排序:升序 ASC,降序 DESC
-- 語法:order by 通過哪個欄位排序,怎麼排
-- 查詢的結果根據 成績降序 排序
select s.studentno,studentname,subjectname,studentresult
from student as s
inner join result as r
on s.studentno = r.studentno
inner join `subject` sub
on r.subjectno = sub.subjectno
where sub.subjectname = '高等數學-4'
-- 對成績進行降序排序
order by studentresult desc

2. 分頁

-- ================  分頁 limit  ===============
-- 100萬
-- 為什麼要分頁?
-- 緩解資料庫壓力,給人的體驗更好

-- 分頁,每頁只顯示五條資料
-- 語法:limit 起始值,頁面的大小
-- limit 0,5	1~5條資料
-- limit 1,5	2~6條資料
select s.studentno,studentname,subjectname,studentresult
from student as s
inner join result as r
on s.studentno = r.studentno
inner join `subject` sub
on r.subjectno = sub.subjectno
where sub.subjectname = '高等數學-4'
order by studentresult desc
limit 0,1

-- 第一頁	limit 0,5
-- 第二頁	limit 5,5
-- 第三頁	limit 10,5

-- 第n頁	limit (n-1) * pageSize, pageSize
-- pageSize:頁面大小
-- (n-1) * pageSize起始值
-- n:當前頁
-- 資料總數/頁面大小 = 總頁數(向上取整,有餘數時總頁數+1)

語法

-- 語法:limit 起始值,頁面的大小

6. 子查詢

where (這個值是計算出來的)

本質:在where語句中巢狀一個子查詢語句

-- =========================== where ======================
-- 1.查詢 高等數學-4 的所有考試結果(學號,科目,成績),降序排列
-- 方式1:使用連線查詢
select `studentno`,`subjectname`,`studentresult`
from `result` as r
inner join `subject` as sub
on r.`subjectno` = sub.`subjectno`
where `subjectname`='高等數學-4'
order by `studentresult` desc

-- 方式二:使用子查詢(由裡及外)
select `studentno`,`subjectno`,`studentresult`
from `result`
where `subjectno`=(
	select `subjectno` from `subject` 
	where `subjectname`='高等數學-4'
)
order by studentresult desc

-- 分數不小於80分的學生的學號和姓名
select distinct s.`studentno`,`studentname`
from `student` as s
inner join `result` as r
on r.`studentno`=s.`studentno`
where r.`studentresult` >= 80

-- 在這個基礎上增加一個科目,高等數學-2
select distinct s.`studentno`,`studentname`
from `student` as s
inner join `result` as r
on r.`studentno`=s.`studentno`
where r.`studentresult` >= 80 and `subjectno`=(
	select `subjectno` from `subject`
	where `subjectname`='高等數學-2'
)

-- 查詢課程為 高等數學-2 且分數不小於 80 的同學的學號和姓名
-- 由裡及外
select `studentno`,`studentname`
from `student` where `studentno` in (
	select `studentno` from `result`
	where `studentresult` >= 80 and `subjectno` = (
		select `subjectno` from `subject`
		where `subjectname` = '高等數學-2'
	)
)

7. 分組和過濾

分組的語法

group by 用於分組的欄位

過濾的語法

having 過濾的條件
-- 注意:having 位於 group by之後!
-- 查詢不同課程的平均分,最高分,最低分,平均分大於80
-- 核心:根據不同的課程分組
select `subjectname` as 科目,avg(`studentresult`) as 平均分,max(`studentresult`) as 最高分,min(`studentresult`) as 最低分
from `result` as r
inner join `subject` as sub
on r.`subjectno` = sub.`subjectno`
-- 通過什麼欄位來分組
group by r.`subjectno`
-- 利用having對分組後的結果進行過濾(此處不能用where是因為where不支援聚合函式),可以使用別名
having 平均分 >= 80

4. MySQL函式

官網:https://dev.mysql.com/doc/refman/5.6/en/sql-function-reference.html

1. 常用函式

-- ========================  常用函式  ==========================
-- 數學運算
select abs(-8)		-- 絕對值
select ceiling(9.4)	-- 向上取整
select floor(9.4)	-- 向下取整
select rand()		-- 返回一個0~1之間的隨機數
select sign(-9)		-- 判斷一個數的符號 0返回0,負數返回-1,正數返回1

-- 字串函式
select char_length('這是一段字串')	-- 字串長度
select concat('這','是','一句話')	-- 拼接字串
select insert('替換失敗',3,2,'成功')	-- 查詢,從某個位置開始替換某個長度的字串,此處的開始位置從1開始計算
select lower('ABCdefg')			-- 轉小寫字母
select upper('ABCdefg')			-- 轉大寫字母
select instr('blue_sky','e')		-- 返回第一次出現的子串的索引
select replace('這是原來的字串','原來','替換後')	-- 替換出現的指定字串
select substr('這是原來的字串',4,2)	-- 返回指定的子字串(源字串,擷取的位置,擷取的長度)
select reverse('這是原來的字串')	-- 反轉字串

-- 查詢姓 將姓趙的同學的姓替換為兆
select replace(`studentname`,'趙','兆') from `student`
where `studentname` like '趙%'

-- 時間和日期函式(重要)
select current_date()		-- 獲取當前日期
select curdate()		-- 獲取當前日期
select now()			-- 獲取當前的時間
select localtime()		-- 獲取本地時間
select sysdate()		-- 獲取系統時間

select year(now())
select month(now())
select day(now())
select hour(now())
select minute(now())
select second(now())

-- 系統
select system_user()		-- 獲取系統的使用者
select user()			-- 獲取系統的使用者
select version()		-- 獲取系統的版本

2. 聚合函式(常用)

函式名稱 描述
count() 計數
sum() 求和
avg() 平均值
max() 最大值
min() 最小值
...
-- ======================  聚合函式  ====================
-- 都能夠統計 表中的資料(想查詢表中有多少個記錄,就用count())
select count(`studentname`) from `student`	-- count(欄位),會忽略所有的null值

select count(*) from `student` 			-- count(*),不會忽略null值,本質:計算行數
select count(1) from `student`			-- count(1),不會忽略null值,本質:計算行數

select sum(`studentresult`) as 總和 from `result`
select avg(`studentresult`) as 平均分 from `result`
select max(`studentresult`) as 最高分 from `result`
select min(`studentresult`) as 最低分 from `result`

3. 資料庫級別的MD5加密(擴充套件)

什麼是MD5?

主要是增強演算法複雜度和不可逆性

MD5不可逆,具體的值MD5是一樣的

MD5破解網站的原理:背後有一個字典,MD5加密後的值 加密前的值

-- ====================  測試MD5 加密  ====================
create table `testMD5` (
  `id` int(4) not null,
  `name` varchar(20) not null,
  `pwd` varchar(50) not null,
  primary key(`id`)
)engine=innodb default charset=utf8

-- 明文密碼
insert into `testMD5` (`id`,`name`,`pwd`) values
(1,'張三','123456'),
(2,'李四','123456'),
(3,'王五','123456')

-- 加密全部的密碼,使用函式md5()
update `testMD5` set pwd=md5(pwd)

-- 插入的時候加密
insert into `testMD5` (`id`,`name`,`pwd`) values
(4,'小明',md5('123456'))

-- 如何校驗:將使用者傳遞進來的密碼進行MD5加密,然後比對加密後的值
select * from `testMD5` where `name` = '小明' and pwd = md5('123456')