一虑乖、 mysql的進(jìn)一步介紹
三范式
1NF:字段不可分屿储,每個(gè)字段是原子級(jí)別的痘括。
不滿足第一范式(1NF)的數(shù)據(jù)庫(kù)就不是關(guān)系數(shù)據(jù)庫(kù)2NF:在1NF基礎(chǔ)上建立萎羔,要求數(shù)據(jù)庫(kù)表中的每個(gè)實(shí)體即每個(gè)記錄行可以被唯一的區(qū)分,這個(gè)唯一屬性即關(guān)鍵字---主鍵
3NF:在2NF基礎(chǔ)上建立医吊,要求一個(gè)關(guān)系表中不包含其他表中包含的非關(guān)鍵字信息钱慢,即不存在傳遞依賴關(guān)系。
SQL分類
SQL語(yǔ)言按照實(shí)現(xiàn)的功能不同卿堂,主要分為3類:數(shù)據(jù)操縱語(yǔ)言(DML)束莫,數(shù)據(jù)定義語(yǔ)言(DDL),數(shù)據(jù)控制語(yǔ)言(DCL)。
- 1.數(shù)據(jù)操縱語(yǔ)言(DML):主要用來(lái)處理數(shù)據(jù)庫(kù)中的數(shù)據(jù)內(nèi)容草描。允許用戶對(duì)數(shù)據(jù)庫(kù)中的數(shù)據(jù)進(jìn)行查詢 览绿,插入,更新和刪除等操作
- 2.數(shù)據(jù)定義語(yǔ)言(DDL):是一組SQL命令穗慕,用于創(chuàng)建和定義數(shù)據(jù)庫(kù)對(duì)象饿敲,并且將對(duì)這些對(duì)象的定義保存到數(shù)據(jù)字典中。通過(guò)DDL語(yǔ)句可以創(chuàng)建數(shù)據(jù)庫(kù)對(duì)象逛绵,修改數(shù)據(jù)庫(kù)對(duì)象和刪除數(shù)據(jù)庫(kù)對(duì)象等诀蓉。
3.數(shù)據(jù)控制語(yǔ)言(DCL):數(shù)據(jù)控制語(yǔ)言用于修改數(shù)據(jù)庫(kù)結(jié)構(gòu)的操作權(quán)限栗竖。DCL語(yǔ)句主要有2種:
按六類說(shuō)明:
DDL數(shù)據(jù)定義語(yǔ)言:create、drop
DML數(shù)據(jù)操作語(yǔ)言:insert渠啤、delete狐肢、update
DCL數(shù)據(jù)控制語(yǔ)言:grant、revoke
DQL數(shù)據(jù)查詢語(yǔ)言:select沥曹、where份名、order by、group by妓美、having
TPL數(shù)據(jù)處理語(yǔ)言:確保被DML影響的表的所有行及時(shí)得以更新僵腺,begin transaction殷费、commit矾芙、rollback
CCL指針控制語(yǔ)言:declare cursor,fetch into和update where current 用于對(duì)一個(gè)或多個(gè)表單獨(dú)的操作责循。
- SQL語(yǔ)句規(guī)范
編寫SQL語(yǔ)句時(shí)需要遵循一定的規(guī)則:
1.SQL關(guān)鍵字贵试、對(duì)象名琉兜、和列名不區(qū)分大小寫。
2.字符值和日期值要區(qū)分大小寫毙玻。
3.在應(yīng)用程序中如果SQL語(yǔ)句文本很長(zhǎng)豌蟋,可以將語(yǔ)句分布到多行上,并且可以通過(guò)使用跳格和縮進(jìn)提高代碼的可讀性
4.SQL*Plus中的SQL語(yǔ)句以分號(hào)(;)結(jié)束桑滩。
二梧疲、單表查詢
語(yǔ)法:
SELECT [DISTINCT] * | 字段 [別名] [,字段 [別名]]
FROM 表名稱 [別名]
[WHERE 條件(S)]
[ORDER BY 字段 [ASC|DESC] [,字段 [ASC|DESC],…]];
消除重復(fù)(DISTINCT)
DISTINCT 關(guān)鍵字可以用于一列,也可以用于多列运准。
只有當(dāng)job 和 deptno中的一條數(shù)據(jù)重復(fù)幌氮,才認(rèn)為是重復(fù)的數(shù)據(jù)。
SELECT DISTINCT DEPTNO,JOB FROM emp
算術(shù)運(yùn)算符
對(duì) NUMBER 型數(shù)據(jù) 使用(+ - * /)算數(shù)操作符創(chuàng)建表達(dá)式胁澳;
對(duì) DATE 型數(shù)據(jù)使用(+ -)算數(shù)操作符創(chuàng)建表達(dá)式该互。
-- 查詢所有員工的年薪(使用別名) SELECT SAL*12 AS SALOFYEAR FROM emp
過(guò)濾查詢(WHERE )
注意:
字符串和日期要用單引號(hào)擴(kuò)起來(lái)
字符串是大小寫不敏感的,日期值是格式大小寫敏感的听哭;
字符串大小寫敏感(binary )
演示:
SELECT * FROM dept WHERE BINARY DNAME = 'sales'
比較運(yùn)算符
= & != & <> & > & >= & < & <=
BETWEEN ... AND ...:在兩值之間慢洋,閉區(qū)間包含
-- 查詢工資在 2000-3000 之間的員工信息 SELECT * FROM emp WHERE SAL BETWEEN 2000 AND 3000
IN:匹配列出的值塘雳;如:IN(1, 2, 3, 4)
-- 查詢工資為 800 或 1600 或 3000 的員工 SELECT * FROM emp WHERE SAL IN (800,1600,3000)
LIKE :匹配字符串模式 如:_ (占位符一個(gè)字符)陆盘、%(通配符多個(gè)字符)
-- 根據(jù)關(guān)鍵字模糊查詢(員工名稱和職位)根據(jù)sal 值查詢 sal=800
SELECT * FROM emp WHERE (ENAME LIKE '%S%' OR JOB LIKE '%C%') AND SAL = 800 注意括號(hào)
IS NULL:是否為空
空值判斷
空值不等于零或空格,也不表示空字符串败明,也就是沒(méi)有值
任何類型的字段都可以允許空值作為值的存在
包括空值的任何算術(shù)表達(dá)式都等于空
函數(shù) IFNULL(expr1, expr2)隘马,若 expr1 不是 NULL,IFNULL() 返回expr1妻顶,否則它返回expr2
-- 查詢所有員工的年薪((月薪 + 獎(jiǎng)金) * 12)
SELECT (SAL + IFNULL(COMM,0)) * 12 FROM emp
邏輯運(yùn)算符
AND:如果組合的條件都是 true酸员,返回 true蜒车;
OR: 之一是 true ,返回 true幔嗦;
NOT:如果下面的條件是 false酿愧,返回 true。
優(yōu)先級(jí)規(guī)則:比較運(yùn)算符 > NOT > AND > OR邀泉。
例子:
SELECT * FROM emp WHERE NOT (SAL = 800 OR SAL = 1600 OR SAL = 3000)
OR條件是獨(dú)立的需要加括號(hào)后再進(jìn)行操作
結(jié)果排序
ASC:升序嬉挡,缺省
DESC:降序
ORDER BY :其子句出現(xiàn)在 SELECT 語(yǔ)句后執(zhí)行,
可以使用別名汇恤,但不能使用加了引號(hào)的別名或列名來(lái)排序庞钢,沒(méi)有效果
三、多表查詢
why use it
需要查詢的數(shù)據(jù)分散在多張表中因谎,只有聯(lián)合多張表才能查詢出期望的數(shù)據(jù)
消除笛卡爾積
其意思:在數(shù)學(xué)中基括,假設(shè)集合 A = {a, b},集合 B = {0, 1, 2}财岔,則兩個(gè)集合的笛卡爾積為 {(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}风皿。
解決方案:在WHERE加入有效的連接條件 ----> 等值連接,注意:連接 n 張表使鹅,至少需要n - 1個(gè)連接條件揪阶。
多表查詢分類
內(nèi)連接查詢:
隱式內(nèi)連接查詢
顯示內(nèi)連接查詢-
外連接查詢:
左外連接查詢
右外連接查詢
全外連接查詢
多表查詢
四、 內(nèi)連接查詢
隱式內(nèi)連接查詢
SELECT [DISTINCT] * | 字段 [別名] [,字段 [別名] ,…]
FROM 表名稱 [別名], [表名稱 [別名] ,…]
[WHERE 條件(S)/等值連接]
[ORDER BY 排序字段 [ASC|DESC] [,排序字段 [ASC|DESC] ,…]];
顯式內(nèi)連接查詢 (常用)
可讀性高
SELECT table1.column, table2.column
FROM table1 [INNER] JOIN table2 ON table1.column1 = table2.column2
WHERE 條件
顯示內(nèi)連接可以看到[INNER] JOIN患朱;
連接條件使用寫在ON子句鲁僚。
-- 查詢員工編號(hào),員工名稱裁厅,員工所屬部門的編號(hào)和名稱
-- 隱式內(nèi)連接查詢
SELECT e.EMPNO, e.ENAME, e.DEPTNO, d.DNAME
FROM emp e,dept d
WHERE e.DEPTNO = d.DEPTNO
-- 顯式內(nèi)連接查詢
SELECT e.EMPNO, e.ENAME, e.DEPTNO, d.DNAME
FROM emp e JOIN dept d
ON e.DEPTNO = d.DEPTNO
五冰沙、外連接查詢
解決什么:
連表查詢時(shí)候,查詢的某個(gè)條件為空導(dǎo)致整條沒(méi)有查出來(lái)
左外連接查詢( LEFT [OUTER] JOIN)
SELECT table1.column, table2.column
FROM table1 LEFT [OUTER] JOIN table2 ON table1.column1 = table2.column2
WHERE 條件
右外連接查詢(RIGHT [OUTER] JOIN)
SELECT table1.column, table2.column
FROM table1 RIGHT [OUTER] JOIN table2 ON(table1.column1 = table2.column2)
WHERE 條件
SELECT emp.EMPNO, emp.ENAME, emp.SAL, dept.DNAME FROM dept RIGHT JOIN emp ON emp.DEPTNO = dept.DEPTNO
查詢的結(jié)果:沒(méi)有的值就是null
六执虹、分組函數(shù)
函數(shù)分類
單行函數(shù):將每條數(shù)據(jù)進(jìn)行獨(dú)立的計(jì)算拓挥,然后每條數(shù)據(jù)得到一條結(jié)果;
多行函數(shù):多條數(shù)據(jù)同時(shí)計(jì)算袋励,最終得到一條結(jié)果數(shù)據(jù)侥啤。也成為聚集函數(shù)、分組函數(shù)茬故,主要用于完成一些統(tǒng)計(jì)功能等等盖灸。
多行函數(shù)(聚合函數(shù))
- 多行函數(shù)也稱聚合函數(shù)(aggregate function)?
聚合函數(shù)對(duì)一組值執(zhí)行計(jì)算并返回單一的值磺芭。
- 聚合函數(shù)有什么特點(diǎn)赁炎?
除了 COUNT 以外,聚合函數(shù)忽略空值钾腺。
聚合函數(shù)經(jīng)常與 SELECT 語(yǔ)句的 GROUP BY 子句一同使用徙垫。
所有聚合函數(shù)都具有確定性讥裤。任何時(shí)候用一組給定的輸入值調(diào)用它們時(shí),都返回相同的值姻报。
標(biāo)量函數(shù):只能對(duì)單個(gè)的數(shù)字或值進(jìn)行計(jì)算己英。主要包括字符函數(shù)、日期/時(shí)間函數(shù)吴旋、數(shù)值函數(shù)和轉(zhuǎn)換函數(shù)這四類剧辐。
COUNT():查詢表中的數(shù)據(jù)記錄;
AVG():求出平均值邮府;
SUM():求和荧关;
MAX():求出最大值;
MIN():求出最小值褂傀。
-- 查詢員工最高工資和最低工資差距
SELECT MAX(SAL) - MIN(SAL) FROM emp
七叠国、分組查詢(GROUP BY)
把表分組未檩,再進(jìn)行操作
SELECT [DISTINCT] *|分組字段1 [別名] [, 分組字段2 [別名] ,…] | 統(tǒng)計(jì)函數(shù)
FROM 表名稱 [別名], [表名稱 [別名] , …]
[WHERE 條件(s)]
[GROUP BY 分組字段1 [, 分組字段2 ,…]]
[ORDER BY 排序字段 ASC | DESC [, 排序字段 ASC | DESC]];
-- 按照職位分組,求出每個(gè)職位的最高和最低工資
SELECT JOB,MAX(SAL) max, MIN(SAL) min FROM emp GROUP BY JOB ORDER BY SAL
- SELECT子句出現(xiàn)的字段粟焊,要不在統(tǒng)計(jì)函數(shù)中冤狡,要不出現(xiàn)在GROUP BY子句中,否則不合理(整體與個(gè)體)项棠;
- 在GROUP BY子句中出現(xiàn)的字段悲雳,可以不出現(xiàn)在SELECT列表中;
- 統(tǒng)計(jì)函數(shù)可以單獨(dú)使用香追,SQL中可以沒(méi)有GROUP BY子句合瓢;
- 在GROUP BY子句中,可以按單列進(jìn)行分組透典,也可以在多列上進(jìn)行分組晴楔,多列分組就是按照多個(gè)字段的組合進(jìn)行分組,最終的結(jié)果也會(huì)按照分組字段進(jìn)行排序顯示峭咒。
分組限定(HAVING)
- 不能在WHERE子句中對(duì)分組限定税弃,限制組須使用HAVING子句;
- 不能在WHERE子句中使用統(tǒng)計(jì)函數(shù)讹语,而在HAVING子句可使用統(tǒng)計(jì)函數(shù)钙皮。
-- 查詢各個(gè)管理人員下員工的平均工資顽决,其中最低工資不能低于1300短条,不計(jì)算老板
SELECT MGR, AVG(SAL), MIN(SAL) AS minsal FROM emp GROUP BY MGR HAVING MGR IS NOT NULL AND minsal >= 1300
八、單行函數(shù)
獲取日期時(shí)間中某個(gè)段
- YEAR(date):返回 date 對(duì)應(yīng)的年份才菠,范圍是從 1000 到 9999茸时;
- MONTH(date):返回 date 對(duì)應(yīng)的月份,范圍時(shí)從 1 到 12赋访;
- DAY(date):獲取日期中的天數(shù)可都,范圍是從 1 到 31;
- HOUR(time):返回 time 對(duì)應(yīng)的小時(shí)數(shù)蚓耽,范圍是從 0 到 23渠牲;
- MINUTE(time):返回 time 對(duì)應(yīng)的分鐘數(shù),范圍是從 0 到 59步悠;
- LAST_DAY(date):獲取一個(gè)日期或日期時(shí)間值签杈,返回該月最后一天對(duì)應(yīng)的值。
本地時(shí)間:
SELECT YEAR(NOW()), MONTH(NOW()), DAY(NOW()), HOUR(NOW()), MINUTE(NOW()), SECOND(NOW())
- 不帶分割符的時(shí)間:
SELECT LAST_INSERT_ID(NOW()) 例子:20200419184521
日期轉(zhuǎn)換為字符串(DATE_FORMAT)
DATE_FORMAT(date, format):把日期轉(zhuǎn)換為字符串鼎兽。
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d')
九答姥、子查詢
- 子查詢指的就是在一個(gè)查詢之中嵌套了其他的若干查詢。
注意:
子查詢一般出現(xiàn)在 FROM 和 WHERE 子句中谚咬;
子查詢要使用圓括號(hào)括起來(lái)鹦付;
將子查詢放在比較運(yùn)算符的右邊(增強(qiáng)可讀性);
子查詢?cè)谥鞑樵兦皥?zhí)行一次择卦,主查詢使用子查詢的結(jié)果敲长;但不宜嵌套過(guò)多;
分類
按查詢結(jié)果分類:
單行單列:只包含一個(gè)字段的查詢秉继,返回的查詢結(jié)果也只包含一行數(shù)據(jù)潘明;
多行單列:只包含了一個(gè)字段,但返回的查詢結(jié)果可能多行或者零行秕噪;
多行多列:包含多個(gè)字段的返回钳降,查詢結(jié)果可能是單行或者多行,好比是一張表腌巾。
單行單列
一般用于 WHERE 之后的子查詢遂填,子查詢結(jié)果是一行一列記錄。
使用單行記錄比較運(yùn)算符:=澈蝙、>吓坚、>=、<灯荧、<=礁击、<>。(單行單列才能用)
-- 查詢出工資比 MARTIN 還要高的全部雇員信息
SELECT * FROM emp WHERE sal > (SELECT sal FROM emp WHERE ename = 'MARTIN')
多行單列
一般也用于 WHERE 子句中,子查詢結(jié)果只有一列哆窿,但是有多行链烈。
IN:與列表中的任意一個(gè)值相等
ANY:與子查詢返回的任意一個(gè)值比較
=ANY:此時(shí)和 IN 操作符相同
>ANY:大于子查詢中最小的數(shù)據(jù)
<ANY:小于子查詢中最大的數(shù)據(jù)
ALL:與子查詢返回的每一個(gè)值比較
>ALL:大于子查詢中最大的數(shù)據(jù)
<ALL:小于子查詢中最小的數(shù)據(jù)
-- 查詢工資等于部門經(jīng)理(職位是 MANAGER)的員工信息。
SELECT * FROM emp WHERE SAL IN (SELECT SAL FROM emp WHERE JOB = 'MANAGER')
多行多列
子查詢的結(jié)果是多行多列挚躯,一般會(huì)把子查詢返回的結(jié)果當(dāng)成一個(gè)臨時(shí)表强衡,接著在臨時(shí)表上繼續(xù)查詢或者連接查詢;
注意:多行多列的子查詢返回的結(jié)果必須要設(shè)置一個(gè)臨時(shí)表名码荔。
-- 查詢出每個(gè)部門的編號(hào)漩勤、名稱、部門人數(shù)缩搅、平均工資 部門名稱
SELECT e.DEPTNO, d.DNAME, COUNT(*), AVG(e.SAL), e.ENAME FROM emp e JOIN dept d ON e.DEPTNO = d.DEPTNO GROUP BY e.DEPTNO