DML操作是指對數據庫中表記錄的操作,主要包括表記錄的插入(insert)、更新(update)、刪除(delete)和查詢(select),是開發人員日常使用最頻繁的操作。
1、插入記錄
INSERT INTO tablename(field1,field2,......fieldn) VALUES(value1,value2,......valuesn);
示例
插入格式1:
mysql> DESC emp; +----------+---------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+---------------+------+-----+---------+-------+ | ename | varchar(20) | YES | | NULL | | | hiredate | date | YES | | NULL | | | sal | decimal(10,2) | YES | | NULL | | | deptno | int(2) | YES | | NULL | | +----------+---------------+------+-----+---------+-------+ 4 rows in set (0.00 sec) mysql> INSERT INTO emp(ename,hiredate,sal,deptno) VALUES('zzx1','2000-01-01','2000',1); Query OK, 1 row affected (0.01 sec)
也可以不用指定字段名稱,但是VALUES后面的順序應該和字段的排列順序一致:
mysql> INSERT INTO emp VALUES('lisa','2003-02-01','3000',2); Query OK, 1 row affected (0.01 sec)
對於含可空字段、非空但是含有默認值的字段、自增字段,可以不用在INSERT后的字段列表里面出現,VALUES后面只寫對應字段名稱的VALUE:
mysql> INSERT INTO emp(ename,sal) VALUES('dony',1000); Query OK, 1 row affected (0.01 sec) mysql> SELECT * FROM emp; +-------+------------+---------+--------+ | ename | hiredate | sal | deptno | +-------+------------+---------+--------+ | zzx1 | 2000-01-01 | 2000.00 | 1 | | lisa | 2003-02-01 | 3000.00 | 2 | | dony | NULL | 1000.00 | NULL | +-------+------------+---------+--------+ 3 rows in set (0.00 sec)
在MySQL中,INSERT語句還可以一次性插入多條記錄:
INSERT INTO tablename(field1,field2,......fieldn) VALUES (record1_value1,record1_value2,......record1_valuen), (record2_value1,record2_value2,......record2_valuen), ...... (recordn_value1,recordn_value2,......recordn_valuen);
示例
mysql> CREATE TABLE dept(deptno INT(4),deptname VARCHAR(20)); Query OK, 0 rows affected (0.02 sec) mysql> DESC dept; +----------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+-------------+------+-----+---------+-------+ | deptno | int(4) | YES | | NULL | | | deptname | varchar(20) | YES | | NULL | | +----------+-------------+------+-----+---------+-------+ 2 rows in set (0.00 sec) mysql> INSERT INTO dept VALUES(1,'dept1'),(2,'dept2'); Query OK, 2 rows affected (0.01 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM dept; +--------+----------+ | deptno | deptname | +--------+----------+ | 1 | dept1 | | 2 | dept2 | +--------+----------+ 2 rows in set (0.00 sec)
2、更新記錄
修改表內的值
UPDATE tablename SET field1=value1,field2=value2,......fieldn=valuen [WHERE CONDITION];
示例:
mysql> SELECT * FROM emp; +-------+------------+---------+--------+ | ename | hiredate | sal | deptno | +-------+------------+---------+--------+ | zzx1 | 2000-01-01 | 2000.00 | 1 | | lisa | 2003-02-01 | 3000.00 | 2 | | dony | NULL | 1000.00 | NULL | +-------+------------+---------+--------+ 3 rows in set (0.00 sec) mysql> UPDATE emp SET sal=4000 WHERE ename='lisa'; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> SELECT * FROM emp; +-------+------------+---------+--------+ | ename | hiredate | sal | deptno | +-------+------------+---------+--------+ | zzx1 | 2000-01-01 | 2000.00 | 1 | | lisa | 2003-02-01 | 4000.00 | 2 | | dony | NULL | 1000.00 | NULL | +-------+------------+---------+--------+ 3 rows in set (0.00 sec)
在MySQL中,UPDATE 命令可以同時更新多個表中數據:
UPDATE t1,t2,...tn SET t1.field1=expr1, t2.field2=expr2, ... tn.fieldn=exprn [WHERE CONDITION];
示例:
同時更新表emp中的字段sal和表dept中的字段deptname:
mysql> SHOW TABLES; +----------------+ | Tables_in_test | +----------------+ | dept | | emp | +----------------+ 2 rows in set (0.00 sec) mysql> SELECT * FROM emp; +-------+------------+---------+--------+ | ename | hiredate | sal | deptno | +-------+------------+---------+--------+ | zzx1 | 2000-01-01 | 2000.00 | 1 | | lisa | 2003-02-01 | 4000.00 | 2 | | dony | NULL | 1000.00 | NULL | +-------+------------+---------+--------+ 3 rows in set (0.00 sec) mysql> SELECT * FROM dept; +--------+----------+ | deptno | deptname | +--------+----------+ | 1 | dept1 | | 2 | dept2 | +--------+----------+ 2 rows in set (0.00 sec) mysql> UPDATE emp a,dept b SET a.sal=a.sal*b.deptno,b.deptname=a.ename WHERE a.deptno=b.deptno; Query OK, 3 rows affected (0.00 sec) Rows matched: 4 Changed: 3 Warnings: 0 mysql> SELECT * FROM emp; +-------+------------+---------+--------+ | ename | hiredate | sal | deptno | +-------+------------+---------+--------+ | zzx1 | 2000-01-01 | 2000.00 | 1 | | lisa | 2003-02-01 | 8000.00 | 2 | | dony | NULL | 1000.00 | NULL | +-------+------------+---------+--------+ 3 rows in set (0.00 sec) mysql> SELECT * FROM dept; +--------+----------+ | deptno | deptname | +--------+----------+ | 1 | zzx1 | | 2 | lisa | +--------+----------+ 2 rows in set (0.00 sec)
注意:多表更新的語法更多地用在了根據一個表的字段,來動態的更新另一個表的字段。
3、刪除記錄
DELETE FROM tablename [WHERE CONDITION];
示例:
mysql> SELECT * FROM emp; +-------+------------+---------+--------+ | ename | hiredate | sal | deptno | +-------+------------+---------+--------+ | zzx1 | 2000-01-01 | 2000.00 | 1 | | lisa | 2003-02-01 | 8000.00 | 2 | | dony | NULL | 1000.00 | NULL | +-------+------------+---------+--------+ 3 rows in set (0.00 sec) mysql> DELETE FROM emp WHERE ename='dony'; Query OK, 1 row affected (0.00 sec) mysql> SELECT * FROM emp; +-------+------------+---------+--------+ | ename | hiredate | sal | deptno | +-------+------------+---------+--------+ | zzx1 | 2000-01-01 | 2000.00 | 1 | | lisa | 2003-02-01 | 8000.00 | 2 | +-------+------------+---------+--------+ 2 rows in set (0.00 sec)
在MySQL中可以一次刪除多個表的數據:
DELETE t1,t2,...tn FROM t1,t2,...tn [WHERE CONDITION];
示例:
mysql> SELECT * FROM emp; +--------+------------+---------+--------+ | ename | hiredate | sal | deptno | +--------+------------+---------+--------+ | zzx1 | 2000-01-01 | 2000.00 | 1 | | lisa | 2003-02-01 | 8000.00 | 2 | | bjguan | 2004-04-02 | 100.00 | 1 | | dony | 2005-02-05 | 5000.00 | 4 | | bzshen | 2005-09-01 | 4000.00 | 5 | +--------+------------+---------+--------+ 5 rows in set (0.00 sec) mysql> SELECT * FROM dept; +--------+----------+ | deptno | deptname | +--------+----------+ | 1 | zzx1 | | 2 | lisa | | 3 | hr | | 5 | fin | +--------+----------+ 4 rows in set (0.00 sec) mysql> DELETE a,b FROM emp a, dept b WHERE a.deptno=b.deptno AND a.deptno=1; Query OK, 3 rows affected (0.01 sec) mysql> SELECT * FROM emp; +--------+------------+---------+--------+ | ename | hiredate | sal | deptno | +--------+------------+---------+--------+ | lisa | 2003-02-01 | 8000.00 | 2 | | dony | 2005-02-05 | 5000.00 | 4 | | bzshen | 2005-09-01 | 4000.00 | 5 | +--------+------------+---------+--------+ 3 rows in set (0.00 sec) mysql> SELECT * FROM dept; +--------+----------+ | deptno | deptname | +--------+----------+ | 2 | lisa | | 3 | hr | | 5 | fin | +--------+----------+ 3 rows in set (0.00 sec)
注意:不管是單表還是多表,不加where條件將會把表的所有記錄刪除,所以操作時一定要小心。
4、查詢記錄
SELECT 基本語法:
SELECT * FROM tablename [WHERE CONDITION];
其中“*”表示要將所有的記錄都選出來,也可以用逗號分割的所有字段來代替。
實際應用中,各種各樣的查詢要求:
(1)查詢不重復的記錄,可以用distinct關鍵字實現:
mysql> SELECT ename,hiredate,sal,deptno FROM emp; +--------+------------+---------+--------+ | ename | hiredate | sal | deptno | +--------+------------+---------+--------+ | lisa | 2003-02-01 | 8000.00 | 1 | | dony | 2005-02-05 | 5000.00 | 4 | | bzshen | 2005-09-01 | 4000.00 | 1 | +--------+------------+---------+--------+ 3 rows in set (0.00 sec) mysql> SELECT DISTINCT deptno FROM emp; +--------+ | deptno | +--------+ | 1 | | 4 | +--------+ 2 rows in set (0.00 sec)
(2)條件查詢
需要查詢所有 deptno為1的記錄:
SELECT * FROM emp WHERE deptno=1;
其中,where 后面的條件除“=” 外,還可以使用 >、<、>=、<=、!=等比較運算符;
多個條件之間還可以使用or、and等邏輯運算符進行多條件聯合查詢:
mysql> SELECT * FROM emp; +--------+------------+---------+--------+ | ename | hiredate | sal | deptno | +--------+------------+---------+--------+ | lisa | 2003-02-01 | 8000.00 | 1 | | dony | 2005-02-05 | 5000.00 | 4 | | bzshen | 2005-09-01 | 4000.00 | 1 | +--------+------------+---------+--------+ 3 rows in set (0.00 sec) mysql> SELECT * FROM emp WHERE deptno=1 AND sal<5000; +--------+------------+---------+--------+ | ename | hiredate | sal | deptno | +--------+------------+---------+--------+ | bzshen | 2005-09-01 | 4000.00 | 1 | +--------+------------+---------+--------+ 1 row in set (0.00 sec)
(3)排序和限制
SELECT * FROM tablename [WHERE CONDITION] [ORDER BY field1 [DESC|ASC], field2 [DESC|ASC],...fieldn [DESC|ASC]];
其中,DESC和ASC是排序關鍵字,
DESC表示按照字段進行降序排列(上大-下小),
ASC則表示升序排列(上小-下大),
如果不寫此關鍵字默認是升序排列。
ORDER BY 后面可以跟多個不同的排列字段,並且每個排序字段可以有不同的排序順序。
如果排序字段的值一樣,則值相同的字段按照第二個排序字段進行排序,以此類推。如果只有一個排序字段,則這字段相同的記錄將會無序排列。
把emp表中的記錄按照工資高低進行顯示:
mysql> SELECT * FROM emp; +--------+------------+---------+--------+ | ename | hiredate | sal | deptno | +--------+------------+---------+--------+ | lisa | 2003-02-01 | 8000.00 | 1 | | dony | 2005-02-05 | 5000.00 | 4 | | bzshen | 2005-09-01 | 4000.00 | 1 | | zzx | 2000-01-01 | 3000.00 | 3 | | bjguan | 2004-04-02 | 3000.00 | 1 | +--------+------------+---------+--------+ 5 rows in set (0.00 sec) mysql> SELECT * FROM emp ORDER BY sal; +--------+------------+---------+--------+ | ename | hiredate | sal | deptno | +--------+------------+---------+--------+ | zzx | 2000-01-01 | 3000.00 | 3 | | bjguan | 2004-04-02 | 3000.00 | 1 | | bzshen | 2005-09-01 | 4000.00 | 1 | | dony | 2005-02-05 | 5000.00 | 4 | | lisa | 2003-02-01 | 8000.00 | 1 | +--------+------------+---------+--------+ 5 rows in set (0.00 sec)
按部門編號,工資排列顯示:
mysql> SELECT * FROM emp ORDER BY deptno; +--------+------------+---------+--------+ | ename | hiredate | sal | deptno | +--------+------------+---------+--------+ | lisa | 2003-02-01 | 8000.00 | 1 | | bzshen | 2005-09-01 | 4000.00 | 1 | | bjguan | 2004-04-02 | 3000.00 | 1 | | zzx | 2000-01-01 | 3000.00 | 3 | | dony | 2005-02-05 | 5000.00 | 4 | +--------+------------+---------+--------+ 5 rows in set (0.00 sec) mysql> SELECT * FROM emp ORDER BY deptno ASC, sal DESC; +--------+------------+---------+--------+ | ename | hiredate | sal | deptno | +--------+------------+---------+--------+ | lisa | 2003-02-01 | 8000.00 | 1 | | bzshen | 2005-09-01 | 4000.00 | 1 | | bjguan | 2004-04-02 | 3000.00 | 1 | | zzx | 2000-01-01 | 3000.00 | 3 | | dony | 2005-02-05 | 5000.00 | 4 | +--------+------------+---------+--------+ 5 rows in set (0.00 sec) mysql> SELECT * FROM emp ORDER BY deptno DESC, sal ASC; +--------+------------+---------+--------+ | ename | hiredate | sal | deptno | +--------+------------+---------+--------+ | dony | 2005-02-05 | 5000.00 | 4 | | zzx | 2000-01-01 | 3000.00 | 3 | | bjguan | 2004-04-02 | 3000.00 | 1 | | bzshen | 2005-09-01 | 4000.00 | 1 | | lisa | 2003-02-01 | 8000.00 | 1 | +--------+------------+---------+--------+ 5 rows in set (0.00 sec)
對於排序后的記錄,如果希望只顯示一部分,而不是全部,這時,就可以使用LIMIT關鍵字來實現,語法:
SELECT ......[LIMIT offset_start,row_count];
其中offset_start表示記錄的起始偏移量,row_count表示顯示的行數。
在默認情況下,起始偏移量為0,只需要寫記錄行數就可以,此時,顯示的實際就是前n條記錄。
示例:顯示emp表中按照sal排序后的前3條記錄:
mysql> SELECT * FROM emp ORDER BY sal; +--------+------------+---------+--------+ | ename | hiredate | sal | deptno | +--------+------------+---------+--------+ | zzx | 2000-01-01 | 3000.00 | 3 | | bjguan | 2004-04-02 | 3000.00 | 1 | | bzshen | 2005-09-01 | 4000.00 | 1 | | dony | 2005-02-05 | 5000.00 | 4 | | lisa | 2003-02-01 | 8000.00 | 1 | +--------+------------+---------+--------+ 5 rows in set (0.00 sec) mysql> SELECT * FROM emp ORDER BY sal LIMIT 3; +--------+------------+---------+--------+ | ename | hiredate | sal | deptno | +--------+------------+---------+--------+ | bjguan | 2004-04-02 | 3000.00 | 1 | | zzx | 2000-01-01 | 3000.00 | 3 | | bzshen | 2005-09-01 | 4000.00 | 1 | +--------+------------+---------+--------+ 3 rows in set (0.00 sec) mysql> SELECT * FROM emp ORDER BY sal LIMIT 2,3; +--------+------------+---------+--------+ | ename | hiredate | sal | deptno | +--------+------------+---------+--------+ | bzshen | 2005-09-01 | 4000.00 | 1 | | dony | 2005-02-05 | 5000.00 | 4 | | lisa | 2003-02-01 | 8000.00 | 1 | +--------+------------+---------+--------+ 3 rows in set (0.00 sec)
LIMIT 經常和ORDER BY一起配合使用來進行記錄的分頁顯示。
注意:limit屬於MySQL擴展SQL92后的語法,在其他數據庫上並不能通用。
(4)聚合
很多情況下,我們需要進行一些匯總操作,比如統計整個公司的人數或者統計每個部門的人數,這是就要用到SQL的集合操作。語法:
SELECT [field1,field2,......fieldn] fun_name FROM tablename [WHERE where_contition] [GROUP BY field1,field2,......fieldn [WITH ROLLUP]] [HAVING where_contition];
對其參數進行以下說明:
- fun_name 表示要做的集合操作,也就是聚合函數,常用的有sum(求和)、count(*)(記錄數)、max(最大值)、min(最小值)。
- GROUP BY 關鍵字表示要進行分類聚合的字段,比如要按照部門分類統計員工數量,部門就應該寫在group by后面。
- WITH ROLLUP 是可選語法,表明是否對分類聚合后的結果進行再匯總。
- HAVING 關鍵字表示對分類后的結果再進行條件的過濾。
注意:having和where的區別在於having是對聚合后的結果進行條件的過濾,而where是在聚合前就對記錄進行過濾,如果邏輯允許,我們盡可能用where先過濾記錄,這樣因為結果集減小,將對聚合的效率大大提高,最后再根據邏輯看是否用having進行再過濾。
聚合還是比較常用的,下面是一些常用示例:
要emp表中統計公司總人數:
mysql> SELECT COUNT(1) FROM emp; +----------+ | COUNT(1) | +----------+ | 5 | +----------+ 1 row in set (0.00 sec)
在此基礎上,要統計各個部門的人數:
mysql> SELECT deptno,COUNT(1) FROM emp GROUP BY deptno; +--------+----------+ | deptno | COUNT(1) | +--------+----------+ | 1 | 3 | | 3 | 1 | | 4 | 1 | +--------+----------+ 3 rows in set (0.00 sec)
更細些,既要統計各部門人數,又要統計總人數:
mysql> SELECT deptno,COUNT(1) FROM emp GROUP BY deptno WITH ROLLUP; +--------+----------+ | deptno | COUNT(1) | +--------+----------+ | 1 | 3 | | 3 | 1 | | 4 | 1 | | NULL | 5 | +--------+----------+ 4 rows in set (0.00 sec)
統計人數大於 1 人的部門:
mysql> SELECT deptno,COUNT(1) FROM emp GROUP BY deptno HAVING COUNT(1)>1; +--------+----------+ | deptno | COUNT(1) | +--------+----------+ | 1 | 3 | +--------+----------+ 1 row in set (0.00 sec)
最后統計公司所有員工的薪水總額、最高和最低薪水:
mysql> SELECT SUM(sal),MAX(sal),MIN(sal) FROM emp; +----------+----------+----------+ | SUM(sal) | MAX(sal) | MIN(sal) | +----------+----------+----------+ | 23000.00 | 8000.00 | 3000.00 | +----------+----------+----------+ 1 row in set (0.00 sec)
(5) 表連接
當需要同時顯示多個表中的字段時,就可以用表連接來實現,這樣的功能。
從大類上分,表連接分為內連接和外連接,它們之間的最主要區別是:
內連接僅選出兩張表中互相匹配的記錄,
而外連接會選出其他不匹配的記錄。我們常用的是內連接。
例如:查詢出所有雇員的名字和所在部門名稱,因為雇員名稱和部門分別存放在表emp和dept中,因此,需要使用表連接來進行查詢:
mysql> SELECT * FROM emp; +--------+------------+---------+--------+ | ename | hiredate | sal | deptno | +--------+------------+---------+--------+ | lisa | 2003-02-01 | 8000.00 | 1 | | dony | 2005-02-05 | 5000.00 | 2 | | bzshen | 2005-09-01 | 4000.00 | 1 | | zzx | 2000-01-01 | 3000.00 | 3 | | bjguan | 2004-04-02 | 3000.00 | 1 | +--------+------------+---------+--------+ 5 rows in set (0.00 sec) mysql> SELECT * FROM dept; +--------+----------+ | deptno | deptname | +--------+----------+ | 1 | tech | | 3 | hr | | 2 | sale | +--------+----------+ 3 rows in set (0.00 sec) mysql> SELECT ename,deptname FROM emp,dept WHERE emp.deptno=dept.deptno; +--------+----------+ | ename | deptname | +--------+----------+ | lisa | tech | | dony | sale | | bzshen | tech | | zzx | hr | | bjguan | tech | +--------+----------+ 5 rows in set (0.00 sec)
外連接有分為左連接和右連接,具體定義如下:
- 左連接:包含所有的左邊表中的記錄甚至是右邊表中沒有和它匹配的記錄
- 右連接:包含所有的右邊表中的記錄甚至是左邊表中沒有和它匹配的記錄
例如,查詢emp中所有用戶和所在部門名稱:
mysql> SELECT * FROM emp; +--------+------------+---------+--------+ | ename | hiredate | sal | deptno | +--------+------------+---------+--------+ | lisa | 2003-02-01 | 8000.00 | 1 | | dony | 2005-02-05 | 5000.00 | 2 | | bzshen | 2005-09-01 | 4000.00 | 1 | | zzx | 2000-01-01 | 3000.00 | 3 | | bjguan | 2004-04-02 | 3000.00 | 1 | | atai | 1999-01-01 | 8000.00 | 4 | +--------+------------+---------+--------+ 6 rows in set (0.00 sec) mysql> SELECT * FROM dept; +--------+----------+ | deptno | deptname | +--------+----------+ | 1 | tech | | 3 | hr | | 2 | sale | +--------+----------+ 3 rows in set (0.00 sec)
mysql> SELECT ename,deptname FROM emp LEFT JOIN dept ON emp.deptno=dept.deptno; +--------+----------+ | ename | deptname | +--------+----------+ | lisa | tech | | bzshen | tech | | bjguan | tech | | zzx | hr | | dony | sale | | atai | NULL | +--------+----------+ 6 rows in set (0.00 sec)
員工atai 部門號為 4,在dept中沒有這個部門。
右連接和左連接類似:
mysql> SELECT ename,deptname FROM dept RIGHT JOIN emp ON dept.deptno=emp.deptno; +--------+----------+ | ename | deptname | +--------+----------+ | lisa | tech | | bzshen | tech | | bjguan | tech | | zzx | hr | | dony | sale | | atai | NULL | +--------+----------+ 6 rows in set (0.01 sec)
(6)子查詢
某些情況,當我們查詢的時候,需要的條件是另一個SELECT語句的結果,這個時候,就要用到子查詢。
用於子查詢的關鍵字主要包括in、not in、=、!=、exists、not exists等。
例如,從emp表中查詢出所有部門在dept表中的所有記錄:
mysql> SELECT * FROM emp; +--------+------------+---------+--------+ | ename | hiredate | sal | deptno | +--------+------------+---------+--------+ | lisa | 2003-02-01 | 8000.00 | 1 | | dony | 2005-02-05 | 5000.00 | 2 | | bzshen | 2005-09-01 | 4000.00 | 1 | | zzx | 2000-01-01 | 3000.00 | 3 | | bjguan | 2004-04-02 | 3000.00 | 1 | | atai | 1999-01-01 | 8000.00 | 4 | +--------+------------+---------+--------+ 6 rows in set (0.00 sec) mysql> SELECT * FROM dept; +--------+----------+ | deptno | deptname | +--------+----------+ | 1 | tech | | 3 | hr | | 2 | sale | | 5 | fin | +--------+----------+ 4 rows in set (0.00 sec)
mysql> SELECT * FROM emp WHERE deptno IN(SELECT deptno FROM dept); +--------+------------+---------+--------+ | ename | hiredate | sal | deptno | +--------+------------+---------+--------+ | lisa | 2003-02-01 | 8000.00 | 1 | | dony | 2005-02-05 | 5000.00 | 2 | | bzshen | 2005-09-01 | 4000.00 | 1 | | zzx | 2000-01-01 | 3000.00 | 3 | | bjguan | 2004-04-02 | 3000.00 | 1 | +--------+------------+---------+--------+ 5 rows in set (0.00 sec)
如果子查詢記錄數唯一,還可以用=代替in:
mysql> SELECT * FROM emp WHERE deptno=(SELECT deptno FROM dept LIMIT 1); +--------+------------+---------+--------+ | ename | hiredate | sal | deptno | +--------+------------+---------+--------+ | lisa | 2003-02-01 | 8000.00 | 1 | | bzshen | 2005-09-01 | 4000.00 | 1 | | bjguan | 2004-04-02 | 3000.00 | 1 | +--------+------------+---------+--------+ 3 rows in set (0.01 sec)
某些情況下,子查詢可以轉化為表連接,例如:
mysql> SELECT * FROM emp WHERE deptno IN(SELECT deptno FROM dept); +--------+------------+---------+--------+ | ename | hiredate | sal | deptno | +--------+------------+---------+--------+ | lisa | 2003-02-01 | 8000.00 | 1 | | dony | 2005-02-05 | 5000.00 | 2 | | bzshen | 2005-09-01 | 4000.00 | 1 | | zzx | 2000-01-01 | 3000.00 | 3 | | bjguan | 2004-04-02 | 3000.00 | 1 | +--------+------------+---------+--------+ 5 rows in set (0.00 sec) 轉換為表連接后: mysql> SELECT emp.* FROM emp,dept WHERE emp.deptno=dept.deptno; +--------+------------+---------+--------+ | ename | hiredate | sal | deptno | +--------+------------+---------+--------+ | lisa | 2003-02-01 | 8000.00 | 1 | | dony | 2005-02-05 | 5000.00 | 2 | | bzshen | 2005-09-01 | 4000.00 | 1 | | zzx | 2000-01-01 | 3000.00 | 3 | | bjguan | 2004-04-02 | 3000.00 | 1 | +--------+------------+---------+--------+ 5 rows in set (0.00 sec)
注意:子查詢和表連接之間的轉換主要應用在兩個方面:
- MySQL 4.1 以前的版本不支持子查詢,需要用表連接來實現子查詢的功能
- 表連接在很多情況下用於優化子查詢
(7)記錄聯合
我們經常會碰到這樣的應用,將兩個表的數據按照一定的查詢條件查詢出來后,將結果合並到一起顯示出來,這個時候,就需要用到union和union all關鍵字來實現這樣的功能,具體語法如下:
SELECT * FROM t1 UNION|UNION ALL SELECT * FROM t2 ...... UNION|UNION ALL SELECT * FROM tn;
UNION 和 UNION ALL的主要區別是 UNION ALL 是把結果集直接合並在一起,而UNION是將UNION ALL后的結果進行一次DISTINCT,去除重復記錄后的結果。
例如,將emp和dept表中的部門編號的集合顯示出來:
mysql> SELECT * FROM emp; +--------+------------+---------+--------+ | ename | hiredate | sal | deptno | +--------+------------+---------+--------+ | lisa | 2003-02-01 | 8000.00 | 1 | | dony | 2005-02-05 | 5000.00 | 2 | | bzshen | 2005-09-01 | 4000.00 | 1 | | zzx | 2000-01-01 | 3000.00 | 3 | | bjguan | 2004-04-02 | 3000.00 | 1 | | atai | 1999-01-01 | 8000.00 | 4 | +--------+------------+---------+--------+ 6 rows in set (0.01 sec) mysql> SELECT * FROM dept; +--------+----------+ | deptno | deptname | +--------+----------+ | 1 | tech | | 3 | hr | | 2 | sale | | 5 | fin | +--------+----------+ 4 rows in set (0.00 sec) mysql> SELECT deptno FROM emp -> UNION ALL -> SELECT deptno FROM dept; +--------+ | deptno | +--------+ | 1 | | 2 | | 1 | | 3 | | 1 | | 4 | | 1 | | 3 | | 2 | | 5 | +--------+ 10 rows in set (0.00 sec)
如果希望將結果去掉重復記錄后顯示:
mysql> SELECT deptno FROM emp -> UNION -> SELECT deptno FROM dept; +--------+ | deptno | +--------+ | 1 | | 2 | | 3 | | 4 | | 5 | +--------+ 5 rows in set (0.00 sec)