MySQL数据库:SQL语句
MySql數(shù)據(jù)庫(kù)系列閱讀
1. SQL概述
1.1 什么是SQL
SQL(Structured Query Language)是“結(jié)構(gòu)化查詢語言”,它是對(duì)關(guān)系型數(shù)據(jù)庫(kù)的操作語言。它可以應(yīng)用到所有關(guān)系型數(shù)據(jù)庫(kù)中,例如:MySQL、Oracle、SQL Server等。SQ標(biāo)準(zhǔn)(ANSI/ISO)有:
- SQL-92:1992年發(fā)布的SQL語言標(biāo)準(zhǔn)
- SQL:1999:1999年發(fā)布的SQL語言標(biāo)簽
- SQL:2003:2003年發(fā)布的SQL語言標(biāo)簽
這些標(biāo)準(zhǔn)就與JDK的版本一樣,在新的版本中總要有一些語法的變化。不同時(shí)期的數(shù)據(jù)庫(kù)對(duì)不同標(biāo)準(zhǔn)做了實(shí)現(xiàn)。
雖然SQL可以用在所有關(guān)系型數(shù)據(jù)庫(kù)中,但很多數(shù)據(jù)庫(kù)還都有標(biāo)準(zhǔn)之后的一些語法,我們可以稱之為“方言”。例如MySQL中的LIMIT語句就是MySQL獨(dú)有的方言,其它數(shù)據(jù)庫(kù)都不支持!當(dāng)然,Oracle或SQL Server都有自己的方言。
SQL的作用:客戶端使用SQL來操作服務(wù)器
1.2 語法要求
SQL標(biāo)準(zhǔn)(例如SQL99,即1999年制定的標(biāo)準(zhǔn)):由國(guó)際標(biāo)準(zhǔn)化組織(ISO)制定的,對(duì)DBMS的統(tǒng)一操作方式(例如相同的語句可以操作:mysql、oracle等)。
SQL方言:某種DBMS不只會(huì)支持SQL標(biāo)準(zhǔn),而且還會(huì)有一些自己獨(dú)有的語法,這就稱之為方言!例如limit語句只在MySQL中可以使用
SQL語法
- SQL語句可以單行或多行書寫,以分號(hào)結(jié)尾
- 可以用空格和縮進(jìn)來來增強(qiáng)語句的可讀性
- 關(guān)鍵字不區(qū)別大小寫,建議使用大寫
2. 分類
- DDL(Data Definition Language):數(shù)據(jù)定義語言,用來定義數(shù)據(jù)庫(kù)對(duì)象:庫(kù)、表、列等
- DML(Data Manipulation Language):數(shù)據(jù)操作語言,用來定義數(shù)據(jù)庫(kù)記錄(數(shù)據(jù))
- DCL(Data Control Language):數(shù)據(jù)控制語言,用來定義訪問權(quán)限和安全級(jí)別
- DQL(Data Query Language):數(shù)據(jù)查詢語言,用來查詢記錄(數(shù)據(jù))
3. DDL:數(shù)據(jù)定義語言
3.1 基本操作
- 查看所有數(shù)據(jù)庫(kù)名稱:SHOW DATABASES;
- 切換數(shù)據(jù)庫(kù):USE mydb1,切換到mydb1數(shù)據(jù)庫(kù);
3.2 操作數(shù)據(jù)庫(kù)
- 創(chuàng)建數(shù)據(jù)庫(kù):CREATE DATABASE [IF NOT EXISTS] mydb1;
例如:CREATE DATABASE mydb1,創(chuàng)建一個(gè)名為mydb1的數(shù)據(jù)庫(kù)。如果這個(gè)數(shù)據(jù)已經(jīng)存在,那么會(huì)報(bào)錯(cuò)。例如CREATE DATABASE IF NOT EXISTS mydb1,在名為mydb1的數(shù)據(jù)庫(kù)不存在時(shí)創(chuàng)建該庫(kù),這樣可以避免報(bào)錯(cuò)
- 刪除數(shù)據(jù)庫(kù):DROP DATABASE [IF EXISTS] mydb1;
例如:DROP DATABASE mydb1,刪除名為mydb1的數(shù)據(jù)庫(kù)。如果這個(gè)數(shù)據(jù)庫(kù)不存在,那么會(huì)報(bào)錯(cuò)。DROP DATABASE IF EXISTS mydb1,就算mydb1不存在,也不會(huì)的報(bào)錯(cuò)
- 修改數(shù)據(jù)庫(kù)編碼:ALTER DATABASE mydb1 CHARACTER SET utf8;
修改數(shù)據(jù)庫(kù)mydb1的編碼為utf8。注意,在MySQL中所有的UTF-8編碼都不能使用中間的“-”,即UTF-8要書寫為UTF8
3.3 數(shù)據(jù)類型
MySQL與Java一樣,也有數(shù)據(jù)類型。MySQL中數(shù)據(jù)類型主要應(yīng)用在列上。常用類型如下:
| int | 整型 |
| double | 浮點(diǎn)型,例如double(5,2)表示最多5位,其中必須有2位小數(shù),即最大值為999.99 |
| decimal | 浮點(diǎn)型,在表單錢方面使用該類型,因?yàn)椴粫?huì)出現(xiàn)精度缺失問題 |
| char | 固定長(zhǎng)度字符串類型 |
| varchar | 可變長(zhǎng)度字符串類型 |
| text | 字符串類型 |
| blob | 字節(jié)類型 |
| date | 日期類型,格式為:yyyy-MM-dd |
| time | 時(shí)間類型,格式為:hh:mm:ss |
| timestamp | 時(shí)間戳類型 |
3.4 操作表
創(chuàng)建表:
CREATE TABLE 表名(列名 列類型,列名 列類型,...... );例如:
CREATE TABLE stu(sid CHAR(6),sname VARCHAR(20),age INT,gender VARCHAR(10) );再例如:
CREATE TABLE emp(eid CHAR(6),ename VARCHAR(50),age INT,gender VARCHAR(6),birthday DATE,hiredate DATE,salary DECIMAL(7,2),resume VARCHAR(1000) ); SHOW TABLES; /*查看當(dāng)前數(shù)據(jù)庫(kù)中所有表名稱*/SHOW CREATE TABLE emp;/*查看emp表的創(chuàng)建語句*/DESC emp; /*查看emp表結(jié)構(gòu)*/DROP TABLE emp; /*刪除emp表*/修改表:add,modify,change,drop
/*修改之添加列:給stu表添加classname列*/ ALTER TABLE stu ADD (classname varchar(100));/*修改之修改列類型:修改stu表的gender列類型為CHAR(2)*/ ALTER TABLE stu MODIFY gender CHAR(2);/*修改之修改列名:修改stu表的gender列名為sex*/ ALTER TABLE stu change gender sex CHAR(2);/*修改之刪除列:刪除stu表的classname列*/ ALTER TABLE stu DROP classname;/*修改之修改表名稱:修改stu表名稱為student*/ ALTER TABLE stu RENAME TO student;4. DML:數(shù)據(jù)操作語言
4.1 插入數(shù)據(jù)
語法:INSERT INTO 表名(列名1,列名2, …) VALUES(值1, 值2)
INSERT INTO stu(sid, sname,age,gender) VALUES('s_1001', 'zhangSan', 23, 'male'); INSERT INTO stu(sid, sname) VALUES('s_1001', 'zhangSan');因?yàn)闆]有插入age和gender列的數(shù)據(jù),所以該條記錄的age和gender值上為NULL
語法:INSERT INTO 表名 VALUES(值1,值2,…)
因?yàn)闆]有指定要插入的列,表示按創(chuàng)建表時(shí)列的順序插入所有列的值:
INSERT INTO stu VALUES('s_1002', 'liSi', 32, 'female');注意:所有字符串?dāng)?shù)據(jù)必須使用單引用!
4.2 修改數(shù)據(jù)
語法:UPDATE 表名 SET 列名1=值1, … 列名n=值n [WHERE 條件]
UPDATE stu SET sname=’zhangSanSan’, age=’32’, gender=’female’ WHERE sid=’s_1001’; UPDATE stu SET sname=’liSi’, age=’20’ WHERE age>50 AND gender=’male’; UPDATE stu SET sname=’wangWu’, age=’30’ WHERE age>60 OR gender=’female’; UPDATE stu SET gender=’female’ WHERE gender IS NULL UPDATE stu SET age=age+1 WHERE sname=’zhaoLiu’;4.3 刪除數(shù)據(jù)
語法:DELETE FROM 表名 [WHERE 條件]
DELETE FROM stu WHERE sid=’s_1001’003B DELETE FROM stu WHERE sname=’chenQi’ OR age > 30; DELETE FROM stu;語法:TRUNCATE TABLE 表名
TRUNCATE TABLE stu;雖然TRUNCATE和DELETE都可以刪除表的所有記錄,但有原理不同。DELETE的效率沒有TRUNCATE高!
TRUNCATE其實(shí)屬性DDL語句,因?yàn)樗窍菵ROP TABLE,再CREATE TABLE。而且TRUNCATE刪除的記錄是無法回滾的,但DELETE刪除的記錄是可以回滾的(回滾是事務(wù)的知識(shí)!)。
5. DCL:數(shù)據(jù)控制語言
5.1 創(chuàng)建用戶
語法:CREATE USER 用戶名@地址 IDENTIFIED BY ‘密碼’;
CREATE USER user1@localhost IDENTIFIED BY ‘123’;CREATE USER user2@’%’ IDENTIFIED BY ‘123’;5.2 給用戶授權(quán)
語法:GRANT 權(quán)限1, … , 權(quán)限n ON 數(shù)據(jù)庫(kù).* TO 用戶名
GRANT CREATE,ALTER,DROP,INSERT,UPDATE,DELETE,SELECT ON mydb1.* TO user1@localhost; GRANT ALL ON mydb1.* TO user2@localhost;5.3 撤銷授權(quán)
語法:REVOKE權(quán)限1, … , 權(quán)限n ON 數(shù)據(jù)庫(kù).* FORM 用戶名
REVOKE CREATE,ALTER,DROP ON mydb1.* FROM user1@localhost;5.4 查看用戶權(quán)限
語法:SHOW GRANTS FOR 用戶名
SHOW GRANTS FOR user1@localhost;5.5 刪除用戶
語法:DROP USER 用戶名
DROP USER user1@localhost;5.6 修改用戶密碼
語法:
USE mysql; UPDATE USER SET PASSWORD=PASSWORD(‘密碼’) WHERE User=’用戶名’ and Host=’IP’; FLUSH PRIVILEGES; UPDATE USER SET PASSWORD=PASSWORD('1234') WHERE User='user2' and Host=’localhost’; FLUSH PRIVILEGES;6. 數(shù)據(jù)查詢語法(DQL)
DQL就是數(shù)據(jù)查詢語言,數(shù)據(jù)庫(kù)執(zhí)行DQL語句不會(huì)對(duì)數(shù)據(jù)進(jìn)行改變,而是讓數(shù)據(jù)庫(kù)發(fā)送結(jié)果集給客戶端。語法:
SELECT selection_list /*要查詢的列名稱*/ FROM table_list /*要查詢的表名稱*/ WHERE condition /*行條件*/ GROUP BY grouping_columns /*對(duì)結(jié)果分組*/ HAVING condition /*分組后的行條件*/ ORDER BY sorting_columns /*對(duì)結(jié)果分組*/ LIMIT offset_start, row_count; /*結(jié)果限定*/創(chuàng)建學(xué)生表:stu
| sid | char(6) | 學(xué)生學(xué)號(hào) |
| sname | varchar(50) | 學(xué)生姓名 |
| age | int | 學(xué)生年齡 |
| gender | varchar(50) | 學(xué)生性別 |
雇員表:emp
| empno | int | 員工編號(hào) |
| ename | varchar(50) | 員工姓 |
| job | varchar(50) | 員工工 |
| mgr | int | 領(lǐng)導(dǎo)編號(hào) |
| hiredate | date | 入職日 |
| sal | decimal(7,2) | 月薪 |
| comm | decimal(7,2) | 獎(jiǎng)金 |
| deptno | int | 部分編號(hào) |
部門表:dept
| deptno | int | 部分編碼 |
| dname | varchar(50) | 部分名稱 |
| loc | varchar(50) | 部分所在地點(diǎn) |
6.1 基礎(chǔ)查詢
6.1.1 查詢所有列
SELECT * FROM stu;6.1.2 查詢指定列
SELECT sid, sname, age FROM stu;6.2 條件查詢
6.2.1 條件查詢介紹
條件查詢就是在查詢時(shí)給出WHERE子句,在WHERE子句中可以使用如下運(yùn)算符及關(guān)鍵字:
- =、!=、<>、<、<=、>、>=
- BETWEEN…AND
- IN(set)
- IS NULL
- AND
- OR
- NOT
6.2.2 查詢性別為女,并且年齡50的記錄
SELECT * FROM stu WHERE gender='female' AND ge<50;6.2.3 查詢學(xué)號(hào)為S_1001,或者姓名為liSi的記錄
SELECT * FROM stu WHERE sid ='S_1001' OR sname='liSi';6.2.4 查詢學(xué)號(hào)為S_1001,S_1002,S_1003的記錄
SELECT * FROM stu WHERE sid IN ('S_1001','S_1002','S_1003');6.2.5 查詢學(xué)號(hào)不是S_1001,S_1002,S_1003的記錄
SELECT * FROM tab_student WHERE s_number NOT IN ('S_1001','S_1002','S_1003');6.2.6 查詢年齡為null的記錄
SELECT * FROM stu WHERE age IS NULL;6.2.7 查詢年齡在20到40之間的學(xué)生記錄
SELECT * FROM stu WHERE age>=20 AND age<=40;或者
SELECT * FROM stu WHERE age BETWEEN 20 AND 40;6.2.8 查詢性別非男的學(xué)生記錄
SELECT * FROM stu WHERE gender!='male';或者
SELECT * FROM stu WHERE gender<>'male';或者
SELECT * FROM stu WHERE NOT gender='male';6.2.9 查詢姓名不為null的學(xué)生記錄
SELECT * FROM stu WHERE NOT sname IS NULL;或者
SELECT * FROM stu WHERE sname IS NOT NULL;6.3模糊查詢
當(dāng)想查詢姓名中包含a字母的學(xué)生時(shí)就需要使用模糊查詢了。模糊查詢需要使用關(guān)鍵字LIKE
6.3.1 查詢姓名由5個(gè)字母構(gòu)成的學(xué)生記錄
SELECT * FROM stu WHERE sname LIKE '_____';模糊查詢必須使用LIKE關(guān)鍵字。其中 “_”匹配任意一個(gè)字母,5個(gè)“_”表示5個(gè)任意字母。
6.3.2 查詢姓名由5個(gè)字母構(gòu)成,并且第5個(gè)字母為“i”的學(xué)生記錄
SELECT * FROM stu WHERE sname LIKE '____i';6.3.3 查詢姓名以“z”開頭的學(xué)生記錄
SELECT * FROM stu WHERE sname LIKE 'z%';其中“%”匹配0~n個(gè)任何字母。
6.3.4 查詢姓名中第2個(gè)字母為“i”的學(xué)生記錄
SELECT * FROM stu WHERE sname LIKE '_i%';6.3.5 查詢姓名中包含“a”字母的學(xué)生記錄
SELECT * FROM stu WHERE sname LIKE '%a%';6.4 字段控制查詢
6.4.1 去除重復(fù)記錄
去除重復(fù)記錄(兩行或兩行以上記錄中系列的上的數(shù)據(jù)都相同),例如emp表中sal字段就存在相同的記錄。當(dāng)只查詢emp表的sal字段時(shí),那么會(huì)出現(xiàn)重復(fù)記錄,那么想去除重復(fù)記錄,需要使用DISTINCT:
SELECT DISTINCT sal FROM emp;6.4.2 查看雇員的月薪與傭金之和
因?yàn)閟al和comm兩列的類型都是數(shù)值類型,所以可以做加運(yùn)算。如果sal或comm中有一個(gè)字段不是數(shù)值類型,那么會(huì)出錯(cuò)。
SELECT *,sal+comm FROM emp;comm列有很多記錄的值為NULL,因?yàn)槿魏螙|西與NULL相加結(jié)果還是NULL,所以結(jié)算結(jié)果可能會(huì)出現(xiàn)NULL。下面使用了把NULL轉(zhuǎn)換成數(shù)值0的函數(shù)IFNULL:
SELECT *,sal+IFNULL(comm,0) FROM emp;6.4.3 給列名添加別名
在上面查詢中出現(xiàn)列名為sal+IFNULL(comm,0),這很不美觀,現(xiàn)在我們給這一列給出一個(gè)別名,為total:
SELECT *, sal+IFNULL(comm,0) AS total FROM emp;給列起別名時(shí),是可以省略AS關(guān)鍵字的:
SELECT *,sal+IFNULL(comm,0) total FROM emp;6.5 排序
6.5.1 查詢所有學(xué)生記錄,按年齡升序排序
SELECT * FROM stu ORDER BY sage ASC;或者
SELECT * FROM stu ORDER BY sage;6.5.2 查詢所有學(xué)生記錄,按年齡降序排序
SELECT * FROM stu ORDER BY age DESC;6.5.3 查詢所有雇員,按月薪降序排序,如果月薪相同時(shí),按編號(hào)升序排序
SELECT * FROM emp ORDER BY sal DESC,empno ASC;7. 聚合函數(shù)
聚合函數(shù)是用來做縱向運(yùn)算的函數(shù):
| COUNT() | 統(tǒng)計(jì)指定列不為NULL的記錄行數(shù) |
| MAX() | 計(jì)算指定列的最大值,如果指定列是字符串類型,那么使用字符串排序運(yùn)算 |
| MIN() | 計(jì)算指定列的最小值,如果指定列是字符串類型,那么使用字符串排序運(yùn)算 |
| SUM() | 計(jì)算指定列的數(shù)值和,如果指定列類型不是數(shù)值類型,那么計(jì)算結(jié)果為0 |
| AVG() | 計(jì)算指定列的平均值,如果指定列類型不是數(shù)值類型,那么計(jì)算結(jié)果為0 |
7.1 COUNT
當(dāng)需要縱向統(tǒng)計(jì)時(shí)可以使用COUNT()。
查詢emp表中記錄數(shù):
SELECT COUNT(*) AS cnt FROM emp;查詢emp表中有傭金的人數(shù):
SELECT COUNT(comm) cnt FROM emp;注意,因?yàn)閏ount()函數(shù)中給出的是comm列,那么只統(tǒng)計(jì)comm列非NULL的行數(shù)。
查詢emp表中月薪大于2500的人數(shù):
SELECT COUNT(*) FROM emp WHERE sal > 2500;統(tǒng)計(jì)月薪與傭金之和大于2500元的人數(shù):
SELECT COUNT(*) AS cnt FROM emp WHERE sal+IFNULL(comm,0) > 2500;查詢有傭金的人數(shù),以及有領(lǐng)導(dǎo)的人數(shù):
SELECT COUNT(comm), COUNT(mgr) FROM emp;7.2 SUM和AVG
當(dāng)需要縱向求和時(shí)使用sum()函數(shù)。
查詢所有雇員月薪和:
SELECT SUM(sal) FROM emp;查詢所有雇員月薪和,以及所有雇員傭金和:
SELECT SUM(sal), SUM(comm) FROM emp;查詢所有雇員月薪+傭金和:
SELECT SUM(sal+IFNULL(comm,0)) FROM emp;統(tǒng)計(jì)所有員工平均工資:
SELECT SUM(sal), COUNT(sal) FROM emp;或者
SELECT AVG(sal) FROM emp;7.3 MAX和MIN
查詢最高工資和最低工資:
SELECT MAX(sal), MIN(sal) FROM emp;8. 分組查詢
當(dāng)需要分組查詢時(shí)需要使用GROUP BY子句,例如查詢每個(gè)部門的工資和,這說明要使用部分來分組。
8.1 分組查詢
查詢每個(gè)部門的部門編號(hào)和每個(gè)部門的工資和:
SELECT deptno, SUM(sal) FROM emp GROUP BY deptno;查詢每個(gè)部門的部門編號(hào)以及每個(gè)部門的人數(shù):
SELECT deptno,COUNT(*) FROM emp GROUP BY deptno;查詢每個(gè)部門的部門編號(hào)以及每個(gè)部門工資大于1500的人數(shù):
SELECT deptno,COUNT(*) FROM emp WHERE sal>1500 GROUP BY deptno;8.2 HAVING子句
查詢工資總和大于9000的部門編號(hào)以及工資和:
SELECT deptno, SUM(sal) FROM emp GROUP BY deptno HAVING SUM(sal) > 9000;注意,WHERE是對(duì)分組前記錄的條件,如果某行記錄沒有滿足WHERE子句的條件,那么這行記錄不會(huì)參加分組;而HAVING是對(duì)分組后數(shù)據(jù)的約束。
9. LIMIT
LIMIT用來限定查詢結(jié)果的起始行,以及總行數(shù)。
9.1 查詢5行記錄,起始行從0開始
SELECT * FROM emp LIMIT 0, 5;注意,起始行從0開始,即第一行開始!
9.2 查詢10行記錄,起始行從3開始
SELECT * FROM emp LIMIT 3, 10;9.3 分頁(yè)查詢
如果一頁(yè)記錄為10條,希望查看第3頁(yè)記錄應(yīng)該怎么查呢?
- 第一頁(yè)記錄起始行為0,一共查詢10行;
- 第二頁(yè)記錄起始行為10,一共查詢10行;
- 第三頁(yè)記錄起始行為20,一共查詢10行;
10. 多表查詢
多表查詢有如下幾種:
- 合并結(jié)果集;
- 連接查詢
- 內(nèi)連接,或等值連接:獲取兩個(gè)表中字段匹配關(guān)系的記錄
- 外連接
- 左外連接:獲取左表所有記錄,即使右表沒有對(duì)應(yīng)匹配的記錄
- 右外連接:用于獲取右表所有記錄,即使左表沒有對(duì)應(yīng)匹配的記錄
- 全外連接(MySQL不支持):只要某一個(gè)表存在匹配,就返回行
- 自然連接
- 子查詢
10.1 合并結(jié)果集
作用:合并結(jié)果集就是把兩個(gè)select語句的查詢結(jié)果合并到一起!
要求:被合并的兩個(gè)結(jié)果:列數(shù)、列類型必須相同
合并結(jié)果集有兩種方式:
- UNION:去除重復(fù)記錄,例如:SELECT * FROM t1 UNION SELECT * FROM t2;
UNION ALL:不去除重復(fù)記錄,例如:SELECT * FROM t1 UNION ALL SELECT * FROM t2。
10.2 連接查詢
連接查詢就是求出多個(gè)表的乘積,例如t1連接t2,那么查詢出的結(jié)果就是t1*t2。
連接查詢會(huì)產(chǎn)生笛卡爾積,假設(shè)集合A={a,b},集合B={0,1,2},則兩個(gè)集合的笛卡爾積為{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}。可以擴(kuò)展到多個(gè)集合的情況。
那么多表查詢產(chǎn)生這樣的結(jié)果并不是我們想要的,那么怎么去除重復(fù)的,不想要的記錄呢,當(dāng)然是通過條件過濾。通常要查詢的多個(gè)表之間都存在關(guān)聯(lián)關(guān)系,那么就通過關(guān)聯(lián)關(guān)系去除笛卡爾積。
你能想像到emp和dept表連接查詢的結(jié)果么?emp一共14行記錄,dept表一共4行記錄,那么連接后查詢出的結(jié)果是56行記錄。
也就你只是想在查詢emp表的同時(shí),把每個(gè)員工的所在部門信息顯示出來,那么就需要使用主外鍵來去除無用信息了。
使用主外鍵關(guān)系做為條件來去除無用信息
SELECT * FROM emp,dept WHERE emp.deptno=dept.deptno;
上面查詢結(jié)果會(huì)把兩張表的所有列都查詢出來,也許你不需要那么多列,這時(shí)就可以指定要查詢的列了。
SELECT emp.ename,emp.sal,emp.comm,dept.dname FROM emp,dept WHERE emp.deptno=dept.deptno;還可以為表指定別名,然后在引用列時(shí)使用別名即可。
SELECT e.ename,e.sal,e.comm,d.dname FROM emp AS e,dept AS d WHERE e.deptno=d.deptno;10.2.1 內(nèi)連接
上面的連接語句就是內(nèi)連接,但它不是SQL標(biāo)準(zhǔn)中的查詢方式,可以理解為方言!SQL標(biāo)準(zhǔn)的內(nèi)連接為:
SELECT * FROM emp e INNER JOIN dept d ON e.deptno=d.deptno;內(nèi)連接的特點(diǎn):查詢結(jié)果必須滿足條件。例如我們向emp表中插入一條記錄:
其中deptno為50,而在dept表中只有10、20、30、40部門,那么上面的查詢結(jié)果中就不會(huì)出現(xiàn)“張三”這條記錄,因?yàn)樗荒軡M足e.deptno=d.deptno這個(gè)條件。
10.2.2 外連接(左連接、右連接)
外連接的特點(diǎn):查詢出的結(jié)果存在不滿足條件的可能。
左連接:讀取左邊數(shù)據(jù)表的全部數(shù)據(jù),即便右邊表無對(duì)應(yīng)數(shù)據(jù)
左連接是先查詢出左表(即以左表為主),然后查詢右表,右表中滿足條件的顯示出來,不滿足條件的顯示NULL。
這么說你可能不太明白,我們還是用上面的例子來說明。其中emp表中“張三”這條記錄中,部門編號(hào)為50,而dept表中不存在部門編號(hào)為50的記錄,所以“張三”這條記錄,不能滿足e.deptno=d.deptno這條件。但在左連接中,因?yàn)閑mp表是左表,所以左表中的記錄都會(huì)查詢出來,即“張三”這條記錄也會(huì)查出,但相應(yīng)的右表部分顯示NULL。
10.2.3 右連接
右連接就是先把右表中所有記錄都查詢出來,然后左表滿足條件的顯示,不滿足顯示NULL。例如在dept表中的40部門并不存在員工,但在右連接中,如果dept表為右表,那么還是會(huì)查出40部門,但相應(yīng)的員工信息為NULL。
SELECT * FROM emp e RIGHT OUTER JOIN dept d ON e.deptno=d.deptno;連接查詢心得:
連接不限與兩張表,連接查詢也可以是三張、四張,甚至N張表的連接查詢。通常連接查詢不可能需要整個(gè)笛卡爾積,而只是需要其中一部分,那么這時(shí)就需要使用條件來去除不需要的記錄。這個(gè)條件大多數(shù)情況下都是使用主外鍵關(guān)系去除。
兩張表的連接查詢一定有一個(gè)主外鍵關(guān)系,三張表的連接查詢就一定有兩個(gè)主外鍵關(guān)系,所以在大家不是很熟悉連接查詢時(shí),首先要學(xué)會(huì)去除無用笛卡爾積,那么就是用主外鍵關(guān)系作為條件來處理。如果兩張表的查詢,那么至少有一個(gè)主外鍵條件,三張表連接至少有兩個(gè)主外鍵條件。
讀取右邊數(shù)據(jù)表的全部數(shù)據(jù),即便左邊邊表無對(duì)應(yīng)數(shù)據(jù)
10.3 全外連接
全外連接(MySQL不支持):只要某一個(gè)表存在匹配,就返回行;可以使用UNION來完成全鏈接
10.4 自然連接
大家也都知道,連接查詢會(huì)產(chǎn)生無用笛卡爾積,我們通常使用主外鍵關(guān)系等式來去除它。而自然連接無需你去給出主外鍵等式,它會(huì)自動(dòng)找到這一等式:
兩張連接的表中名稱和類型完全一致的列作為條件,例如emp和dept表都存在deptno列,并且類型一致,所以會(huì)被自然連接找到!
當(dāng)然自然連接還有其他的查找條件的方式,但其他方式都可能存在問題!
SELECT * FROM emp NATURAL JOIN dept; SELECT * FROM emp NATURAL LEFT JOIN dept; SELECT * FROM emp NATURAL RIGHT JOIN dept;10.5 子查詢
子查詢就是嵌套查詢,即SELECT中包含SELECT,如果一條語句中存在兩個(gè),或兩個(gè)以上SELECT,那么就是子查詢語句了。
- 子查詢出現(xiàn)的位置:
- where后,作為條件的一部分;
- from后,作為被查詢的一條表;
- 當(dāng)子查詢出現(xiàn)在where后作為條件時(shí),還可以使用如下關(guān)鍵字:
- any
- all
- 子查詢結(jié)果集的形式:
- 單行單列(用于條件)
- 單行多列(用于條件)
- 多行單列(用于條件)
- 多行多列(用于表)
10.5.1 工資高于甘寧的員工。
分析:
查詢條件:工資>甘寧工資,其中甘寧工資需要一條子查詢。
第一步:查詢甘寧的工資
SELECT sal FROM emp WHERE ename='甘寧'第二步:查詢高于甘寧工資的員工
SELECT * FROM emp WHERE sal > (${第一步})結(jié)果:
SELECT * FROM emp WHERE sal > (SELECT sal FROM emp WHERE ename='甘寧')子查詢作為條件
子查詢形式為單行單列
10.5.2 工資高于30部門所有人的員工信息
分析:
查詢條件:工資高于30部門所有人工資,其中30部門所有人工資是子查詢。高于所有需要使用all關(guān)鍵字。
第一步:查詢30部門所有人工資
SELECT sal FROM emp WHERE deptno=30;第二步:查詢高于30部門所有人工資的員工信息
SELECT * FROM emp WHERE sal > ALL (${第一步})結(jié)果:
SELECT * FROM emp WHERE sal > ALL (SELECT sal FROM emp WHERE deptno=30)- 子查詢作為條件
- 子查詢形式為多行單列(當(dāng)子查詢結(jié)果集形式為多行單列時(shí)可以使用ALL或ANY關(guān)鍵字)
10.5.3 查詢工作和工資與殷天正完全相同的員工信息
分析:
查詢條件:工作和工資與殷天正完全相同,這是子查詢
第一步:查詢出殷天正的工作和工資
SELECT job,sal FROM emp WHERE ename='殷天正'第二步:查詢出與殷天正工作和工資相同的人
SELECT * FROM emp WHERE (job,sal) IN (${第一步})結(jié)果:
SELECT * FROM emp WHERE (job,sal) IN (SELECT job,sal FROM emp WHERE ename='殷天正')- 子查詢作為條件
- 子查詢形式為單行多列
10.5.4 查詢員工編號(hào)為1006的員工名稱、員工工資、部門名稱、部門地址
分析:
查詢列:員工名稱、員工工資、部門名稱、部門地址
查詢表:emp和dept,分析得出,不需要外連接(外連接的特性:某一行(或某些行)記錄上會(huì)出現(xiàn)一半有值,一半為NULL值)
條件:員工編號(hào)為1006
第一步:去除多表,只查一張表,這里去除部門表,只查員工表
SELECT ename, sal FROM emp e WHERE empno=1006第二步:讓第一步與dept做內(nèi)連接查詢,添加主外鍵條件去除無用笛卡爾積
SELECT e.ename, e.sal, d.dname, d.loc FROM emp e, dept d WHERE e.deptno=d.deptno AND empno=1006第二步中的dept表表示所有行所有列的一張完整的表,這里可以把dept替換成所有行,但只有dname和loc列的表,這需要子查詢。
第三步:查詢dept表中dname和loc兩列,因?yàn)閐eptno會(huì)被作為條件,用來去除無用笛卡爾積,所以需要查詢它。
SELECT dname,loc,deptno FROM dept;第四步:替換第二步中的dept
SELECT e.ename, e.sal, d.dname, d.loc FROM emp e, (SELECT dname,loc,deptno FROM dept) d WHERE e.deptno=d.deptno AND e.empno=1006- 子查詢作為表
- 子查詢形式為多行多列
11. MySQL 索引
MySQL索引的建立對(duì)于MySQL的高效運(yùn)行是很重要的,索引可以大大提高M(jìn)ySQL的檢索速度。
索引分單列索引和組合索引。單列索引,即一個(gè)索引只包含單個(gè)列,一個(gè)表可以有多個(gè)單列索引,但這不是組合索引。組合索引,即一個(gè)索包含多個(gè)列。
創(chuàng)建索引時(shí),你需要確保該索引是應(yīng)用在 SQL 查詢語句的條件(一般作為 WHERE 子句的條件)。
實(shí)際上,索引也是一張表,該表保存了主鍵與索引字段,并指向?qū)嶓w表的記錄。
上面都在說使用索引的好處,但過多的使用索引將會(huì)造成濫用。因此索引也會(huì)有它的缺點(diǎn):雖然索引大大提高了查詢速度,同時(shí)卻會(huì)降低更新表的速度,如對(duì)表進(jìn)行INSERT、UPDATE和DELETE。因?yàn)楦卤頃r(shí),MySQL不僅要保存數(shù)據(jù),還要保存一下索引文件。
建立索引會(huì)占用磁盤空間的索引文件。
11.1 普通索引
CREATE INDEX indexName ON mytable(username(length)); //創(chuàng)建索引 ALTER mytable ADD INDEX [indexName] ON (username(length)) ;//修改表結(jié)構(gòu) DROP INDEX [indexName] ON mytable; //刪除索引11.2 唯一索引
CREATE UNIQUE INDEX indexName ON mytable(username(length)) ;//創(chuàng)建索引 ALTER mytable ADD UNIQUE [indexName] ON (username(length)) ;修改表結(jié)構(gòu)11.3 使用ALTER 命令添加和刪除索引
//該語句添加一個(gè)主鍵,這意味著索引值必須是唯一的,且不能為NULL ALTER TABLE tbl_name ADD PRIMARY KEY (column_list);//這條語句創(chuàng)建索引的值必須是唯一的(除了NULL外,NULL可能會(huì)出現(xiàn)多次) ALTER TABLE tbl_name ADD UNIQUE index_name (column_list);// 添加普通索引,索引值可出現(xiàn)多次 ALTER TABLE tbl_name ADD INDEX index_name (column_list);//該語句指定了索引為 FULLTEXT ,用于全文索引 ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list);總結(jié)
以上是生活随笔為你收集整理的MySQL数据库:SQL语句的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android序列化与反序列化
- 下一篇: MySQL数据库:完整性约束