0731-MySql(2)
----------------------------------------------------------以下的可以看作跟=,<,>等等一樣的特殊運(yùn)算符----------------------------------------
模糊查詢(低效率):
like?
% 替換0,1或以上的字符
_ 替換1個(gè)
rlike
這個(gè)是以正則查找
用法示例:select name from students where name rlike "^周.*";
范圍查詢
in 在某個(gè)非連續(xù)范圍內(nèi) ;not in 反之
select name,age from students where age in (12,18,34);
between 在某個(gè)連續(xù)的范圍內(nèi)(包含頭包含尾) ; not between 反之 但是這是一種固定用法 不能age not (between 18 and 34),會(huì)掛
select name,age from students where age not between 18 and 34;
判斷空
is null; 或者 is NULL;
is not null; 反之
select name,height from students where height is null;
到此為止------------------------------------------------------------------------------------------------------------------------------------------
聚合函數(shù)(可以就看作python里一樣的函數(shù))
count 計(jì)數(shù)
select count(*) as 男性人數(shù) from students where gender = "男";
select count(*) as 女性人數(shù) from students where gender = "女";
# 前面應(yīng)該記錄過(guò)as...吧?
max/min 最大/最小值
select max(age) from students where gender = 2;
select min(height) from students where gender = 1;
sum 求和
select sum(age) from students;
avg 求平均值
select avg(age) from students;
說(shuō)了這么多,這個(gè)應(yīng)該也看出來(lái)了可以支持運(yùn)算的,所以還可以這么寫
select sum(age)/count(*) from students;
round 保留小數(shù)位數(shù),【四舍五入】
select round( (sum(age)/count(*)) , 2 ) from students;
# C語(yǔ)言底層在內(nèi)存中存儲(chǔ)數(shù)據(jù)的時(shí)候都是約等于,而絕大多數(shù)語(yǔ)言的解釋器都是用C語(yǔ)言編寫的,所以他們也會(huì)約等于,就產(chǎn)生了誤差
# 而在銀行等等這些對(duì)數(shù)據(jù)要求很精密的地方,直接把數(shù)據(jù)擴(kuò)大多少倍(100,1000,1^4...),最終記得要除上相同的倍數(shù)
# 總之,這種不能有誤差的地方在存儲(chǔ)的時(shí)候不要用小數(shù)
select round(avg(height), 2) from students;
如果round前面加個(gè)name,那是不能的,會(huì)掛,需要用到接下來(lái)的功能-->分組
分組(一般跟聚合一起用)
group by
select gender from students group by gender; --根據(jù)性別分組
前面寫上條件,要唯一能標(biāo)記這個(gè)組的條件
跟聚合函數(shù)混在一起:
select gender,count(*) from students group by gender;
這時(shí)候是把分的組里面的每個(gè)元素進(jìn)行操作,不是對(duì)原表操作
而且不止count,剛才所學(xué)的所有的聚合函數(shù)都能使用
select gender, round(sum(age)/count(*),2) from students group by gender;
還可以寫上group_concat(name)來(lái)把具體的name拿出來(lái),還可以加條件,加在group by前面
select gender,group_concat(name, age, id) from students where gender=1 group by gender;
group_concat實(shí)際上是把這幾個(gè)東西鏈接在一起顯示出來(lái)
所以上面是這仨東西連在一起輸出的,那么我們可以在中間加任意字符分割,就是這樣group_concat("名字:",name, ",年齡:", age, ",ID:", id)
having
這個(gè)感覺(jué)跟在group前面加where很像
select group,group_concat(name),avg(age) from students group gender having avg(age) > 30;
但是他跟where還是不一樣,having是對(duì)這個(gè)組進(jìn)行判斷,where是直接對(duì)原表進(jìn)行判斷
鏈接查詢:多個(gè)表的關(guān)聯(lián)查詢
# 回顧 外鍵:存的是某個(gè)表的主鍵,幫我們限制數(shù)據(jù)的范圍
直白來(lái)講,就是把多個(gè)表中的共有數(shù)據(jù)取出來(lái)查詢
一共分為三種:
1. 內(nèi)連接查詢
inner join --固定語(yǔ)法,不能拆開(kāi)
-- ? ? ?表A ? ? 表B
select * from students inner join classes;
這個(gè)就是簡(jiǎn)單的把倆表合起來(lái),只是語(yǔ)法正確而已
on 后面加條件
select * from students inner join classes on students.cls_id = classes.id;
這個(gè)是找的到的就合并并顯示,找不到的干脆不會(huì)顯示,也就是超過(guò)3(因?yàn)閏lasses表id一共三個(gè))的
這個(gè)合并是咋合并呢,很簡(jiǎn)單,直接把倆拼接一起(
就是左邊是表A所有符合On的數(shù)據(jù),右邊是所有對(duì)應(yīng)的表B的數(shù)據(jù)
可以分別讓他顯示一部分,就像這樣
select students.*, classes.name from students inner join classes on students.cls_id = classes.id; --可以短一點(diǎn),用as
select s.*, c.name from students as s inner join classes as c on s.cls_id = c.id;
總結(jié)下,on后面的對(duì)的上的話(產(chǎn)生交集),他就取兩個(gè)表的交際部分一一對(duì)應(yīng),你也有,他也有才顯示
還可以跟order by結(jié)合,好像是個(gè)排序的玩意,反正前面講過(guò)...應(yīng)該
select c.name, s.* from students as s inner join classes as c on s.slc_id = c.id order by c.name,s.id;
左連接和右連接(大體都是外連接):
直白來(lái)講:內(nèi)間接取交接,左連接是哪個(gè)表在左邊,以這個(gè)表為基準(zhǔn)去取東西,取不出來(lái)的默認(rèn)為null
語(yǔ)法(左連接)left join --還真是好理解(
select c.name, s.* from students as s left join classes as c on s.slc_id = c.id order by c.name,s.id
這個(gè)輸出結(jié)果會(huì)多三個(gè),這仨是右邊找不到的,會(huì)顯示null
再和前面結(jié)合下
select c.name, s.* from students as s left join classes as c on s.slc_id = c.id order by c.name,s.id where c.id is null;
where c.id is null 跟 having c.id is null一樣的
自關(guān)聯(lián):自己其中一個(gè)字段跟另一個(gè)字段關(guān)聯(lián)
比如地址
id? ?name? pid
1? ? ?xxx1? ? ? null
2? ? ?xxx2? ? ? null
3? ? ?xx1? ? ? ? 2
4? ? ?xx2? ? ? ? 2
5? ? ?x1 ? ? 3
6? ? ?x2? ? ? ? ?3
就像這樣,pid表示他的上級(jí)(老大)
子查詢:比子關(guān)聯(lián)稍微慢一點(diǎn)
一個(gè)select里面套另外一個(gè)select
select * from students where height = (select max(height) from students);
數(shù)據(jù)庫(kù)(表)設(shè)計(jì):
有專業(yè)的軟件可以設(shè)計(jì),如果大公司還有專門的人員負(fù)責(zé)
繼軟件三大范式之后,數(shù)據(jù)庫(kù)設(shè)計(jì)三大范式(其實(shí)有8種,但是一般前三種就夠):
1NF: 一個(gè)數(shù)據(jù)一個(gè)字段,不要一堆數(shù)據(jù)塞一個(gè)字段里,要求把每個(gè)信息拆成一個(gè)字段
2NF:如果表里面的主鍵有多個(gè)字段組成,直接依賴于所有的主鍵,我理解就是如果有別的主鍵就把他專門拆開(kāi)拆成一個(gè)新的數(shù)據(jù)表,新表有個(gè)外關(guān)聯(lián)跟原本的表關(guān)聯(lián)
3NF:如果一堆信息都依賴于某個(gè)主鍵,那個(gè)主鍵依賴于另一個(gè)主鍵,那他們不能把信息都塞一個(gè)表里
什么意思呢,就是比如一個(gè)訂單表
里面有訂單ID,訂單信息,客戶ID,客戶信息
那么客戶ID依賴于訂單ID對(duì)吧,那他們就要拆開(kāi)
訂單ID單獨(dú)一張表,里面有訂單信息,ID和客戶ID
客戶ID單獨(dú)一張表,這樣的話如果這個(gè)客戶多次下單就不會(huì)出現(xiàn)重復(fù)的客戶信息了
這三大范式遵循了可以達(dá)到節(jié)省空間的效果,極大的縮減了數(shù)據(jù)的規(guī)模和重復(fù)性
而且把這個(gè)拆分成這樣就解耦了,這個(gè)有點(diǎn)像MVC架構(gòu)奉行的理念,高內(nèi)聚,低耦合,各干各的
這就是為什么叫關(guān)系型數(shù)據(jù)庫(kù),關(guān)系非常強(qiáng),后面還會(huì)學(xué)的NoSql等等非關(guān)系型數(shù)據(jù)庫(kù)這些就不一樣,他們是一張表就是一張表,沒(méi)有任何關(guān)系
E-R模型
E(entry)實(shí)體,就像一個(gè)類一樣,一個(gè)抽象的模板
R(relationship)關(guān)系,描述兩個(gè)實(shí)體間的規(guī)則,可以為一對(duì)一,多對(duì)一等等,這個(gè)也是需要一個(gè)字段來(lái)描述的
一對(duì)一和多對(duì)一很簡(jiǎn)單,都是在左邊加,但是多對(duì)多呢
多對(duì)多有點(diǎn)麻煩,得新開(kāi)個(gè)表,存儲(chǔ)每個(gè)表的主鍵,這樣的表我們稱之為聚合表
python操作mysql
流程:導(dǎo)入-->創(chuàng)建connection對(duì)象-->創(chuàng)建cursor-->執(zhí)行mysql語(yǔ)句...-->關(guān)閉cursor-->關(guān)閉connection對(duì)象-->結(jié)束
基本就是操作中間部分,其他都是差不多固定的
? ? conn = connect(host="localhost", port=3306, user="root", password="123456", database="jing_dong", charset='utf-8')
? ? cs1 = conn.cursor()
? ??
? ? cs1.execute("--執(zhí)行的sql語(yǔ)句")
? ? # 這個(gè)東西的返回值是生效的行數(shù),也就是所查詢到的行數(shù),要數(shù)據(jù)的話就調(diào)游標(biāo)對(duì)象對(duì)應(yīng)的行數(shù)
? ? cs1.fetchone()? # 這個(gè)是一條一條取,返回元組類型
? ? cs1.fetchmany() # 返回個(gè)元組套元組,里面輸入的參數(shù)決定返回幾個(gè),
sql注入攻擊
就是直接寫sql語(yǔ)句進(jìn)去,讓原本的name,變成一個(gè)sql語(yǔ)句
原來(lái)有個(gè)網(wǎng)址,烏云WooYun,東哥原來(lái)經(jīng)常進(jìn)去看,確實(shí)能學(xué)到不少東西,有幫人經(jīng)常把他們sql攻擊的圖片啥的全截圖下來(lái)發(fā)上去曬
后來(lái)東哥自己去試了下把某通快遞公司的訂單號(hào)全給拿出來(lái)了,里面收貨人的手機(jī)號(hào),地址啥的全都有
而且人家明明告訴了某通說(shuō)讓他改,人就是不改,后來(lái)什么中通啊,圓通啊,國(guó)通啊數(shù)據(jù)都泄露了,反正各大企業(yè)都泄露了
(網(wǎng)址已經(jīng)被封了,被國(guó)家約談了,抓了百多個(gè)人進(jìn)去,現(xiàn)在法律規(guī)定,只要獲取個(gè)人信息累加50條以上就寄了)
[我還真找到烏云遺產(chǎn)了,甚至找到個(gè)群和烏云的網(wǎng)址備份,15年的群了,8年了居然還沒(méi)掛,具體信息存儲(chǔ)于本篇附件內(nèi),不會(huì)跟筆記一起發(fā)布]
以及其實(shí)可以試試我自己寫個(gè)mysql注入的字典,存txt里,里面寫有可能的sql注入語(yǔ)句,程序接收返回結(jié)果,用循環(huán)自動(dòng)化測(cè)試
找到結(jié)果后記錄到log里,不過(guò)這應(yīng)該是個(gè)很長(zhǎng)的過(guò)程,而且?guī)缀跽也坏綔y(cè)試案例,只能希望自己寫個(gè)網(wǎng)站或者試試阿三哥的那個(gè)平臺(tái)能不能用吧
? ??
? ? cs1.close()
? ? conn.close()