回顧
字段類型(列類型):數(shù)值型,時間日期型和字符串類型
數(shù)值型:整型和小數(shù)型(浮點型和定點型)
時間日期型:datetime,date,time,timestamp,year
字符串類型:定長,變長,文本字符串(text和blob),枚舉和集合
mysql記錄長度:65535字節(jié),varchar達不到理論長度,NULL占用一個字節(jié),text
文本不占用記錄長度(但是本身占據(jù)十個字節(jié))
字段屬性:空屬性,列描述,默認值
字段屬性
主鍵,唯一鍵,自增長。
主鍵
主鍵:primary key,主要的鍵。一張表只能有一個字段可以使用對應(yīng)的鍵。用來唯一的約束
該字段里面的數(shù)據(jù)不能重復(fù)。這種稱之為主鍵。
一張表只能有最多一個主鍵。
增加主鍵
SQL操作中有很多種方式可以給表增加主鍵:大體分為三種。
方案1:在創(chuàng)建表的時候,直接在字段之后,跟primary key關(guān)鍵字(主鍵本身不允許為空)
優(yōu)點:非常直接,缺點:只能使用一個字段作為主鍵。
方案2:在創(chuàng)建表的時候,在所有字段之后,使用primary key(主鍵字段列表)來創(chuàng)建主鍵(如果有多個字段作為主鍵,可以是復(fù)合主鍵)
方案3:當(dāng)表已經(jīng)創(chuàng)建好之后,額外追加主鍵:可以通過修改表字段屬性,也可以直接追加。
alter table 表名 add primary key (字段列表);
前提:表中字段對應(yīng)的數(shù)據(jù)本身是獨立的(不重復(fù),因為它沒辦法去修改數(shù)據(jù))
主鍵約束
主鍵對應(yīng)的字段中的數(shù)據(jù)不允許重復(fù):一旦重復(fù),數(shù)據(jù)操作失敗(增和改)
更新主鍵&刪除主鍵
沒有辦法更新主鍵,主鍵必須先刪除,才能增加
alter table 表名 drop primary key;
主鍵分類
在實際創(chuàng)建表的過程中,很少使用真實業(yè)務(wù)數(shù)據(jù)作為主鍵字段(業(yè)務(wù)主鍵:如學(xué)號,課程號);
大部分的時候是使用邏輯性的字段(字段沒有業(yè)務(wù)含義,值是什么都沒關(guān)系),將這種字段的
主鍵稱之為邏輯主鍵
create table my_student(
id int primary key auto_increment comment '邏輯主鍵:自增長', -- 邏輯主鍵
number char(10) not null comment '學(xué)號',
name varchar(10) not null
)
自動增長
新增自增長
自增長:當(dāng)對應(yīng)的字段不給值或者說給默認值或者給NULL的時候,會自動的被系統(tǒng)觸發(fā),系統(tǒng)
會從當(dāng)前字段中已有的最大值再進行+1操作,得到一個新的不同的值。
自增長通常是跟主鍵搭配。
自增長特點:auto_increment
- 任何一個字段要做自增長必須前提是本身是一個索引(key一欄有值,主鍵一定是索引(主鍵索引),索引卻不一定是主鍵)
- 自增長字段必須是數(shù)字(整型)
- 一張表最多只能有一個自增長
自增長的使用
當(dāng)自增長被給定的值為NULL或者默認值的時候會觸發(fā)自動增長
自增長如果對應(yīng)的字段輸入了值,那么自增長失效:但是下一次還是能夠正確的自增長(從最大值+1)
如何確定下一次是什么自增長呢?可以通過查看表創(chuàng)建語句看到。
修改自增長
自增長如果涉及到字段改變:必須先刪除自增長,后增加(因為一張表只能有一個自增長)
修改當(dāng)前自增長已經(jīng)存在的值:修改只能比當(dāng)前已有的自增長的最大值當(dāng)前,不能小(小不生效)
alter table 表名 auto_increment = 值;
向上修改可以
思考:為什么自增長是從1開始?為什么每次都是自增1呢?
所有系統(tǒng)的表現(xiàn)(如字符集,校對集)都是由系統(tǒng)內(nèi)部的變量進行控制的。
查看自增長對應(yīng)的變量:show variables like 'auto_increment%';
可以修改變量實現(xiàn)不同的效果:修改是對整個數(shù)據(jù)修改,而不是單張表(會話級)
set auto_increment = 5; -- 一次自增5
測試效果:自動使用自增長
由于系統(tǒng)誤差引起。
刪除自增長
自增長是字段的一個屬性:可以通過modify來進行修改(保證字段沒有auto_increment即可)
alter table 表名 modify 字段 類型;
唯一鍵
一張表往往有很多字段需要具有唯一性,數(shù)據(jù)不能重復(fù):但是一張表只能有一個主鍵,
唯一鍵(unique key)就可以解決表中有多個字段需要唯一性約束的問題。
唯一鍵的本質(zhì)與主鍵差不多:唯一鍵默認允許自動為空,而且可以多個為空(空字段不參與唯一性比較)
增加唯一鍵
基本與主鍵差不多:三種方案
方案1:在創(chuàng)建表的時候,直接在字段之后,跟unique/unique key
方案2:在創(chuàng)建表的時候,在所有字段之后,使用unique -- 復(fù)合唯一鍵
方案3:當(dāng)表已經(jīng)創(chuàng)建好之后增加唯一鍵
唯一鍵約束
唯一鍵與主鍵本質(zhì)相同:唯一區(qū)別就是唯一鍵默認允許為空,而且是多個為空。
如果唯一鍵也不允許為空:與主鍵的約束作用是一直的。
更新唯一鍵&刪除唯一鍵
更新唯一鍵:先刪除后新增(唯一鍵可以有多個:可以不刪除)
刪除唯一鍵
alter table 表名 drop unqiue key; -- 錯誤:唯一鍵有多個
alter table 表名 drop index 索引名字; -- 唯一鍵默認使用字段名作為索引名字
索引
幾乎所有的索引都是建立在字段之上。
索引:系統(tǒng)根據(jù)某種算法,將已有的數(shù)據(jù)(未來可能新增的數(shù)據(jù)),單獨建立一個文件:文件能夠?qū)崿F(xiàn)
快速的匹配數(shù)據(jù),并且能夠快速的找到對應(yīng)表中的記錄。
索引的意義:
- 提升查詢數(shù)據(jù)的效率
- 約束數(shù)據(jù)的有效性(唯一性等)
增加索引的前提條件:索引本身會產(chǎn)生索引文件(有時候有可能比數(shù)據(jù)文件還大),會非常耗費磁盤空間。
如果某個字段需要作為查詢的條件經(jīng)常使用,那么可以使用索引(一定會想辦法增加)
如果某個字段需要進行有效性的約束,也可能使用索引(主鍵,唯一鍵)
mysql中提供了多種索引:
- 主鍵索引:primary key
- 唯一鍵索引:unique key
- 全文索引:fulltext index
- 普通索引:index
全文索引:針對文章內(nèi)部的關(guān)鍵字進行索引
全文索引最大的問題:在于如何確定關(guān)鍵字
英文很容易:英文單詞與單詞之間有空格
中文很難:沒有空格,而且中文可以各種隨意組合(分詞:sphinx)
關(guān)系
將實體與實體的關(guān)系,反映到最終數(shù)據(jù)庫表的設(shè)計上來:將關(guān)系分成3種:一對一、一對多(多對一)和多對多。
所有的關(guān)系都是指表與表之間的關(guān)系
一對一
一對一:一張表的一條記錄一定只能與另外一張表的一條記錄進行對應(yīng);反之亦然。
id(PRI) | 姓名 | 性別 | 年齡 | 身高 | 體重 | 婚姻 | 籍貫 | 住址 | 聯(lián)系人 |
---|
學(xué)生表:姓名,性別,年齡,身高,體重,婚姻,籍貫,住址,聯(lián)系人
id(PRI) | 姓名 | 性別 | 年齡 | 身高 | 體重 | 婚姻 | 籍貫 | 住址 | 聯(lián)系人 |
---|
表設(shè)計成以上這種形式:符合要求,其中姓名,性別,年齡,身高,體重都屬于常用數(shù)據(jù);但是
婚姻,籍貫,住址,聯(lián)系人屬于不常用數(shù)據(jù)。如果每次都是查詢所有數(shù)據(jù),不常用的數(shù)據(jù)就會影響效率,實際又不用
解決方案:將常用的和不常用的信息分離存儲,分成兩張表
id(PRI) | 姓名 | 性別 | 年齡 | 身高 | 體重 |
---|
常用信息表
id(PRI) | 姓名 | 性別 | 年齡 | 身高 | 體重 |
---|
id(PRI) | 婚姻 | 籍貫 | 住址 | 聯(lián)系人 |
---|
不常用信息表:保證不常用信息與常用信息一定能夠?qū)?yīng)上:找一個具有唯一性(確定記錄)
的字段來共同連接兩張表
id(PRI) | 婚姻 | 籍貫 | 住址 | 聯(lián)系人 |
---|
一個常用表中的一條記錄:永遠只能在一張不常用表中匹配一條記錄;反過來,一個不常用表中的一條記錄
在常用表中也只能匹配一條記錄:一對一的關(guān)系
一對多
一對多:一張表中有一條記錄可以對應(yīng)另一張表中的多條記錄;但是反過來,另一張表的一條記錄只能對應(yīng)第一張表
的一條記錄,這種關(guān)系就是 一對多或多對一
母親與孩子的關(guān)系:兩個實體
id(PRI) | 名字 | 年齡 |
---|
母親表:
id(PRI) | 名字 | 年齡 |
---|
id(PRI) | 名字 | 年齡 |
---|
孩子表:
id(PRI) | 名字 | 年齡 |
---|
以上關(guān)系:一個母親可以在孩子表中找到多條記錄(也有可能是一條);但是一個孩子只能找到一個母親:是一種典型的
一對多的關(guān)系
以上設(shè)計解決了實體的設(shè)計表問題,但是沒有解決關(guān)系問題:孩子找不到母親,目前也找不到孩子。
解決方案:在某一張表中增加一個字段,能夠找到另外一張表中的記錄:應(yīng)該在孩子表中增加一個字段
指向母親表:因為孩子表的記錄只能匹配到一條母親表的記錄。
id(PRI) | 名字 | 年齡 |
---|
母親表:
id(PRI) | 名字 | 年齡 |
---|
id(PRI) | 名字 | 年齡 | 母親ID |
---|
孩子表:
id(PRI) | 名字 | 年齡 | 母親ID |
---|
多對多
多對多:一張表中(A)的一條記錄能夠?qū)?yīng)另外一張表B中的多條記錄;同時B表中的一條記錄也能對應(yīng)A表中的多條記錄,
多對多的關(guān)系
老師教學(xué):老師和學(xué)生
t_id(PRI) | 姓名 | 性別 |
---|---|---|
1 | A | 男 |
2 | B | 女 |
老師表:
t_id(PRI) | 姓名 | 性別 |
---|---|---|
1 | A | 男 |
2 | B | 女 |
s_id(PRI) | 姓名 | 性別 |
---|---|---|
1 | 張三 | 男 |
2 | 小芳 | 女 |
學(xué)生表:
s_id(PRI) | 姓名 | 性別 |
---|---|---|
1 | 張三 | 男 |
2 | 小芳 | 女 |
以上設(shè)計方案:實現(xiàn)了實體的設(shè)計,但是沒有維護實體的關(guān)系
一個老師教過多個學(xué)生:一個學(xué)生也被多個老師教過。
解決方案:在學(xué)生表中增加老師字段:不管在哪張表中增加字段,都會出現(xiàn)一個問題:該字段要保存多個數(shù)據(jù),而且
是與其他表有關(guān)系的字段,不符合表設(shè)計規(guī)范:因此要增加一張新表:專門維護兩張表之間的關(guān)系。
t_id(PRI) | 姓名 | 性別 |
---|---|---|
1 | A | 男 |
2 | B | 女 |
老師表:
t_id(PRI) | 姓名 | 性別 |
---|---|---|
1 | A | 男 |
2 | B | 女 |
s_id(PRI) | 姓名 | 性別 |
---|---|---|
1 | 張三 | 男 |
2 | 小芳 | 女 |
學(xué)生表:
s_id(PRI) | 姓名 | 性別 |
---|---|---|
1 | 張三 | 男 |
2 | 小芳 | 女 |
id(PRI) | t_id | s_id |
---|---|---|
1 | 1 | 1 |
2 | 1 | 2 |
3 | 2 | 1 |
中間關(guān)系表:老師與學(xué)生的關(guān)系
id(PRI) | t_id | s_id |
---|---|---|
1 | 1 | 1 |
2 | 1 | 2 |
3 | 2 | 1 |
增加中間表之后:中間表與老師形成了一對多的關(guān)系:而且中間表是多表,維護了能夠唯一找到
一表的關(guān)系;同樣的,學(xué)生表與中間表也是一個一對多的關(guān)系,一對多的關(guān)系可以匹配到關(guān)聯(lián)表
之間的數(shù)據(jù)。
學(xué)生找老師:找出學(xué)生id -> 中間表尋找匹配多條記錄 -> 老師表匹配(一條記錄)
老師找學(xué)生:找出老師id -> 中間表尋找匹配多條記錄 -> 學(xué)生表匹配(一條記錄)
范式
范式:Normal Format,是一種離散數(shù)學(xué)中的知識,是為了解決一種數(shù)據(jù)的存儲存儲與優(yōu)化的問題;
保存的數(shù)據(jù)存儲之后,凡是能夠通過關(guān)系尋找出來的數(shù)據(jù),堅決不再重復(fù)存儲:終極目標(biāo)是為了
減少數(shù)據(jù)的冗余。
范式:是一種分層結(jié)構(gòu)的規(guī)范,分為六層:每一層逗比都比上一層更加嚴(yán)格:若要滿足下一層范式,前提
是滿足上一層范式。
六層范式:1NF,2NF,3NF....6NF,1NF是最底層,要求最低,6NF是最高層,最嚴(yán)格。
mysql屬于關(guān)系型數(shù)據(jù)庫,有空間浪費,因此它要致力于節(jié)省存儲空間:與范式所要解決的問題不謀而合:在
設(shè)計數(shù)據(jù)庫時,會利用范式來指導(dǎo)設(shè)計。
但是數(shù)據(jù)庫不單是要解決空間問題,還要保證效率問題,而范式只為解決空間問題,所以數(shù)據(jù)庫的設(shè)計又不可能
完全按照范式的要求實現(xiàn):一般情況下,只有前三種凡是滿足需要。
范式在數(shù)據(jù)庫的設(shè)計當(dāng)中是有指導(dǎo)意義:但不是強制規(guī)范
1NF
第一范式:在設(shè)計表存儲數(shù)據(jù)的時候,如果表中設(shè)計的字段所存儲的數(shù)據(jù),在取出來使用之前還需要額外的處理(拆分),那么
說明表的設(shè)計不滿足第一范式:第一范式要求字段的數(shù)據(jù)具有原子性(不可再分)。
講師P | 性別 | 班級P | 教室 | 代課時間 | 代課時間(開始,結(jié)束) |
---|---|---|---|---|---|
朱元璋 | Male | php0226 | D302 | 30天 | 2014-02-27,2014-05-05 |
朱元璋 | Male | php0320 | B206 | 30天 | 2014-03-21,2014-05-30 |
李世民 | Male | php0320 | B206 | 15天 | 2014-06-01,2014-06-20 |
講師代課表
講師P | 性別 | 班級P | 教室 | 代課時間 | 代課時間(開始,結(jié)束) |
---|---|---|---|---|---|
朱元璋 | Male | php0226 | D302 | 30天 | 2014-02-27,2014-05-05 |
朱元璋 | Male | php0320 | B206 | 30天 | 2014-03-21,2014-05-30 |
李世民 | Male | php0320 | B206 | 15天 | 2014-06-01,2014-06-20 |
上表設(shè)計不存在問題:但是如果需求是將數(shù)據(jù)查出來之后,要求顯示一個老師從什么時候開始
上課,到什么時候結(jié)課,那么將需要對代課時間進行拆分:不符合1NF(數(shù)據(jù)不具有原子性,可以再拆分)
講師p | 性別 | 班級P | 教室 | 代課時間 | 開始 | 結(jié)束 |
---|---|---|---|---|---|---|
朱元璋 | Male | php0226 | D302 | 30天 | 2014-02-27 | 2014-05-05 |
朱元璋 | Male | php0320 | B206 | 30天 | 2014-03-21 | 2014-05-30 |
李世民 | Male | php0320 | B206 | 15天 | 2014-06-01 | 2014-06-20 |
解決方案:將代課時間拆分成兩個字段。
講師p | 性別 | 班級P | 教室 | 代課時間 | 開始 | 結(jié)束 |
---|---|---|---|---|---|---|
朱元璋 | Male | php0226 | D302 | 30天 | 2014-02-27 | 2014-05-05 |
朱元璋 | Male | php0320 | B206 | 30天 | 2014-03-21 | 2014-05-30 |
李世民 | Male | php0320 | B206 | 15天 | 2014-06-01 | 2014-06-20 |
2NF
第二范式:在數(shù)據(jù)表設(shè)計的過程中,如果有復(fù)合主鍵(多字段主鍵),且表中有字段并不是由整個主鍵來確定,
而是依賴主鍵中的某個字段(主鍵的部分):存在字段依賴主鍵的部分的問題,稱之為部分依賴:第二范式就是
要解決表設(shè)計不允許出現(xiàn)部分依賴。
講師p | 性別 | 班級P | 教室 | 代課時間 | 開始 | 結(jié)束 |
---|---|---|---|---|---|---|
朱元璋 | Male | php0226 | D302 | 30天 | 2014-02-27 | 2014-05-05 |
朱元璋 | Male | php0320 | B206 | 30天 | 2014-03-21 | 2014-05-30 |
李世民 | Male | php0320 | B206 | 15天 | 2014-06-01 | 2014-06-20 |
講師代課表
講師p | 性別 | 班級P | 教室 | 代課時間 | 開始 | 結(jié)束 |
---|---|---|---|---|---|---|
朱元璋 | Male | php0226 | D302 | 30天 | 2014-02-27 | 2014-05-05 |
朱元璋 | Male | php0320 | B206 | 30天 | 2014-03-21 | 2014-05-30 |
李世民 | Male | php0320 | B206 | 15天 | 2014-06-01 | 2014-06-20 |
以上表中:因為講師沒有辦法作為獨立主鍵,需要結(jié)合班級才能作為主鍵(復(fù)合主鍵:一個老師在一個班級永遠只帶一個
階段的課):代課時間,開始和結(jié)束字段都與當(dāng)前的代課主鍵(講師和班級)相關(guān):但是性別并不依賴班級,教室不依賴
講師:性別只依賴講師,教室只依賴班級:出現(xiàn)了性別和教室依賴主鍵中的一部分:部分依賴,不符合第二范式。
解決方案1:可以將性別與講師單獨成表,班級與教室也單獨成表。
IDP | 講師 | 性別 | 班級 | 教室 | 代課時間 | 開始 | 結(jié)束 |
---|---|---|---|---|---|---|---|
1 | 朱元璋 | Male | php0226 | D302 | 30天 | 2014-02-27 | 2014-05-05 |
2 | 朱元璋 | Male | php0320 | B206 | 30天 | 2014-03-21 | 2014-05-30 |
3 | 李世民 | Male | php0320 | B206 | 15天 | 2014-06-01 | 2014-06-20 |
解決方案2:取消復(fù)合主鍵,使用邏輯主鍵。
IDP | 講師 | 性別 | 班級 | 教室 | 代課時間 | 開始 | 結(jié)束 |
---|---|---|---|---|---|---|---|
1 | 朱元璋 | Male | php0226 | D302 | 30天 | 2014-02-27 | 2014-05-05 |
2 | 朱元璋 | Male | php0320 | B206 | 30天 | 2014-03-21 | 2014-05-30 |
3 | 李世民 | Male | php0320 | B206 | 15天 | 2014-06-01 | 2014-06-20 |
ID = 講師 + 班級(業(yè)務(wù)邏輯約束:復(fù)合唯一鍵)
3NF
要滿足第三范式,必須滿足第二范式
第三范式:理論上講,應(yīng)該一張表中的所有字段都應(yīng)該直接依賴主鍵(邏輯主鍵:代表的是業(yè)務(wù)主鍵),如果表設(shè)計中存在
一個字段,并不是直接依賴主鍵,而是通過某個非主鍵字段依賴,最終實現(xiàn)依賴主鍵:把這種不是直接依賴主鍵,而是依
賴非主鍵字段的依賴關(guān)系稱之為傳遞依賴。第三范式就是要解決傳遞依賴的問題。
IDP | 講師 | 性別 | 班級 | 教室 | 代課時間 | 開始 | 結(jié)束 |
---|---|---|---|---|---|---|---|
1 | 朱元璋 | Male | php0226 | D302 | 30天 | 2014-02-27 | 2014-05-05 |
2 | 朱元璋 | Male | php0320 | B206 | 30天 | 2014-03-21 | 2014-05-30 |
3 | 李世民 | Male | php0320 | B206 | 15天 | 2014-06-01 | 2014-06-20 |
講師代課表
IDP | 講師 | 性別 | 班級 | 教室 | 代課時間 | 開始 | 結(jié)束 |
---|---|---|---|---|---|---|---|
1 | 朱元璋 | Male | php0226 | D302 | 30天 | 2014-02-27 | 2014-05-05 |
2 | 朱元璋 | Male | php0320 | B206 | 30天 | 2014-03-21 | 2014-05-30 |
3 | 李世民 | Male | php0320 | B206 | 15天 | 2014-06-01 | 2014-06-20 |
以上設(shè)計方案:性別依賴講師存在,講師依賴主鍵,教室依賴班級,班級依賴主鍵:性別和教室都存在傳遞依賴。
解決方案:將存在傳遞依賴的字段、以及依賴的字段本身單獨取出,形成一個單獨的表,然后在需要對應(yīng)的信息
的時候,使用對應(yīng)的實體表的主鍵加進來。
IDP | 講師ID | 班級ID | 代課時間 | 開始 | 結(jié)束 |
---|---|---|---|---|---|
1 | 1 | 10 | 30天 | 2014-02-27 | 2014-05-05 |
2 | 1 | 12 | 30天 | 2014-03-21 | 2014-05-30 |
3 | 2 | 12 | 15天 | 2014-06-01 | 2014-06-20 |
講師代課表
IDP | 講師ID | 班級ID | 代課時間 | 開始 | 結(jié)束 |
---|---|---|---|---|---|
1 | 1 | 10 | 30天 | 2014-02-27 | 2014-05-05 |
2 | 1 | 12 | 30天 | 2014-03-21 | 2014-05-30 |
3 | 2 | 12 | 15天 | 2014-06-01 | 2014-06-20 |
IDP | 講師 | 性別 |
---|---|---|
1 | 朱元璋 | Male |
2 | 朱元璋 | Male |
3 | 李世民 | Male |
講師表
IDP | 講師 | 性別 |
---|---|---|
1 | 朱元璋 | Male |
2 | 朱元璋 | Male |
3 | 李世民 | Male |
IDP | 班級 | 教室 |
---|---|---|
10 | php0226 | D302 |
12 | php0320 | B206 |
12 | php0320 | B206 |
班級表
IDP | 班級 | 教室 |
---|---|---|
10 | php0226 | D302 |
12 | php0320 | B206 |
12 | php0320 | B206 |
講師表中其實ID=講師,班級表中其實ID=班級
逆規(guī)范化
有時候,在設(shè)計表的時候,如果一張表中有幾個字段是需要從另外的表中去獲取信息,理論上講,的確可以
獲取到想要的數(shù)據(jù),但是就是效率低一點。會刻意的在某些表中,不去保存另外表的主鍵(邏輯主鍵),而是
直接保存想要的信息:這樣一來,在查詢數(shù)據(jù)的時候,一張表可以直接提供數(shù)據(jù),而不需要多表查詢(效率低),
但是會導(dǎo)致數(shù)據(jù)冗余增加。
IDP | 講師 | 教室 | 代課時間 | 開始 | 結(jié)束 |
---|---|---|---|---|---|
1 | 朱元璋 | php0226 | 30天 | 2014-02-27 | 2014-05-05 |
2 | 朱元璋 | php0320 | 30天 | 2014-03-21 | 2014-05-30 |
3 | 李世民 | php0320 | 15天 | 2014-06-01 | 2014-06-20 |
如講課代課信息表
IDP | 講師 | 教室 | 代課時間 | 開始 | 結(jié)束 |
---|---|---|---|---|---|
1 | 朱元璋 | php0226 | 30天 | 2014-02-27 | 2014-05-05 |
2 | 朱元璋 | php0320 | 30天 | 2014-03-21 | 2014-05-30 |
3 | 李世民 | php0320 | 15天 | 2014-06-01 | 2014-06-20 |
逆規(guī)范化:磁盤利用率與效率的對抗。
數(shù)據(jù)高級操作
數(shù)據(jù)操作:增刪改查
新增數(shù)據(jù)
基本語法:insert into 表名 [(字段列表)] values (值列表);
在數(shù)據(jù)插入的時候,假設(shè)主鍵對應(yīng)的值已經(jīng)存在:插入一定會失敗
主鍵沖突
當(dāng)主鍵存在沖突的時候(Duplicate key),可以選擇性的進行處理:更新和替換
主鍵沖突:更新操作
insert into 表名 [(字段列表:包含主鍵)] values (值列表) on duplicate key update 字段 = 新值;
注意上圖中有兩行受到影響:因此是更新而不是插入操作。
主鍵沖突:替換
replace into 表名 [(字段列表:包含主鍵)] values (值列表);
注意還是會有兩行受到影響,先刪除再插入
蠕蟲復(fù)制
蠕蟲復(fù)制:從已有的數(shù)據(jù)中去獲取數(shù)據(jù),然后將數(shù)據(jù)又進行新增操作:數(shù)據(jù)成倍的增加。
表創(chuàng)建高級操作:從已有表創(chuàng)建新表(復(fù)制表結(jié)構(gòu))
create table 表名 like 數(shù)據(jù)庫.表名;
蠕蟲復(fù)制:先插出數(shù)據(jù),然后將查出的數(shù)據(jù)新增一遍
insert into 表名 [(字段列表)] select 字段列表/* from 數(shù)據(jù)表名;
蠕蟲復(fù)制的意義
- 從已有表中拷貝數(shù)據(jù)到新表中
- 可以迅速的讓表中的數(shù)據(jù)膨脹到一定的數(shù)量級:測試表的壓力以及效率
更新數(shù)據(jù)
基本語法:update 表名 set 字段 = 值 [where條件];
高級更新語法:update 表名 set 字段 = 值 [where條件] [limit更新數(shù)量];
刪除數(shù)據(jù)
與更新類似:可以通過limit來限制數(shù)量
delete from 表名 [where條件] [limit數(shù)量];
刪除:如果表中存在主鍵自增長,那么當(dāng)刪除之后,自增長不會還原
如何還原自增長?
思路:數(shù)據(jù)的刪除是不會改變表結(jié)構(gòu)的,只能刪除表重建表
truncate 表名; -- 先刪除改變,后新增改變
查詢數(shù)據(jù)
基本語法
select 字段列表/* from 表名 [where條件];
完整語法
select [select選項] 字段列表[字段別名]/* from 數(shù)據(jù)源 [where條件子句][group by子句][having子句][order by子句][limit子句];
select選項
select選項:select對查出來的結(jié)果的處理方式
all:默認的,保留所有的結(jié)果
distinct:去重,查出來的結(jié)果,將重復(fù)(所有字段都相同)給去除
字段別名
字段別名:當(dāng)數(shù)據(jù)進行查詢出來的時候,有時候名字并不一定就滿足需求(多表查詢的時候,會有同名字段)。需要對字段進行重命名:別名
語法:
字段名 [as] 別名;
數(shù)據(jù)源
數(shù)據(jù)源:數(shù)據(jù)的來源,關(guān)系型數(shù)據(jù)庫的來源都是數(shù)據(jù)表:本質(zhì)上只要保證數(shù)據(jù)類似二維表,最終都可以作為數(shù)據(jù)源
數(shù)據(jù)源分為多種:單表數(shù)據(jù)源,多表數(shù)據(jù)源,查詢語句
單表數(shù)據(jù)源:select * from 表名;
多表數(shù)據(jù)源:select * from 表名1,表名2....
從一張表中取出一條記錄,去另外一張表中匹配所有記錄,而且全部保留:(記錄數(shù)和字段數(shù)),
將這種結(jié)果稱為:笛卡爾積(交叉連接):笛卡爾積沒有什么卵用,應(yīng)該應(yīng)該盡量避免。
子查詢:數(shù)據(jù)的來源是一條查詢語句(查詢語句的結(jié)果是二維表)
select * from (select語句) as 表名;
where子句
where子句:用來判斷數(shù)據(jù),篩選數(shù)據(jù)
where子句返回結(jié)果:0或者1,0代表false,1代表true
判斷條件
比較運算符:>,<,>=,<=,!=,<>,=,like,between and,in/not in
邏輯運算符:&&(and),||(or),!(not)
where原理:where是唯一一個直接從磁盤獲取數(shù)據(jù)的時候就開始判斷的條件:從磁盤取出一條記錄,開始進行where判斷:判斷的結(jié)果
如果成立保存到內(nèi)存;如果失敗直接放棄。
條件查詢1:要求找出學(xué)生id為1或者為3的學(xué)生
條件查詢2:查出區(qū)間落在180,190身高之間的學(xué)生
between本身是閉區(qū)間;between左邊的值必須小于或者等于右邊的值
group by子句
group by:分組的意思,根據(jù)某個字段進行分組(相同的放一組,不同的分到不同組)
基本語法:group by 字段名;
分組的意義:是為了統(tǒng)計數(shù)據(jù)(按組統(tǒng)計:按分組的字段進行數(shù)據(jù)統(tǒng)計)
SQL提供了一系列統(tǒng)計函數(shù)
count():統(tǒng)計分組后的記錄數(shù):每一組有多少記錄
max():統(tǒng)計每組中最大的值(根據(jù)字段)
min():統(tǒng)計最小值
avg():統(tǒng)計平均值
sum():統(tǒng)計和
count函數(shù):里面可以使用兩種參數(shù):*代表統(tǒng)計記錄;字段名代表統(tǒng)計對應(yīng)的字段(NULL不統(tǒng)計)
分組會自動排序:根據(jù)分組字段--默認升序
group by 字段 [asc|desc]; -- 對分組的結(jié)果合并之后的整個結(jié)果進行排序
多字段分組:先根據(jù)一個字段進行分組,然后對分組后的結(jié)果
有一個函數(shù):可以對分組的結(jié)果中的某個字段進行字符串連接(保留改組所有的某個字段):group_concat(字段);
回溯統(tǒng)計:with rollup:任何一個分組后都有一個一個小組,最后都需要向上級進行匯報統(tǒng)計:根據(jù)當(dāng)前分組字段。這就是回溯統(tǒng)計:回溯
統(tǒng)計的時候會將分組字段置空
多字段回溯:考慮第一層分組會有此回溯:第二次分組要看第一次分組的組數(shù),組數(shù)是多少,回溯就是多少,然后加上第一層回溯即可。
having子句
having子句:與where子句一樣:進行條件判斷的
where是針對磁盤數(shù)據(jù)進行判斷:進入到內(nèi)存之后,會進行分組操作:分組結(jié)果就需要having來處理
having能做where能做的幾乎所有事情,但是where卻不能做having能做的很多事情
- 分組統(tǒng)計的結(jié)果或者說統(tǒng)計函數(shù)都只有having能夠使用
- having能夠使用字段別名,where不能:where是從磁盤讀取數(shù)據(jù),而名字只可能是字段名,別名是在
字段進入內(nèi)存之后才會產(chǎn)生。
order by子句
order by:排序,根據(jù)某個字段進行升序或者降序排序,依賴校對集
使用基本語法
order by 字段名 [asc|desc]; -- asc是升序(默認的),desc是降序
排序可以進行多字段排序:先根據(jù)某個字段進行排序,然后排序好的內(nèi)部,再按照某個數(shù)據(jù)進行再次排序
limit子句
limit子句是一種限制結(jié)果的語句:限制數(shù)量
limit有兩種使用方式
方案1:只用來限制長度(數(shù)據(jù)量):limit 數(shù)據(jù)量;
方案2:限制起始位置,限制數(shù)量:limit 起始位置, 長度;
方案2主要用來實現(xiàn)數(shù)據(jù)的分頁:為用戶節(jié)省時間,提高服務(wù)器的響應(yīng)效率,減少資源的浪費
對于用戶來講:可以點擊的分頁按鈕:1,2,3,4
對于服務(wù)器來講:根據(jù)用戶選擇的頁碼來獲取不同的數(shù)據(jù):limit offset, length;
length:每頁顯示的數(shù)據(jù)量:基本不變
offset: offset = (頁碼 - 1) * 每頁顯示量