MySQL使用入門--DML語句


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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM