SQL DML 資料操縱語句
阿新 • • 發佈:2018-12-31
前言
DML(Data Manipulation Language)語句:資料操縱語句,用於新增、刪除、更新和查詢資料庫記錄,並檢查資料完整性。常用的語句關鍵字主要包括 insert、delete、update 和 select 等。
常用約束型別
約束型別 解釋 not null 非空約束,設定的內容在新增資料的時候不能是 null 的 unique 唯一約束,值是唯一的 primary key 主鍵約束,非空唯一 auto_increment 主鍵自增約束,主鍵為數值型 foreign key 外來鍵約束,B 表使用 A 表的主鍵 常用 where 查詢條件
where 條件 解釋 > < <= >= <> 大於、小於、大於(小於)等於、不等於 between...and... 在某一區間,閉區間,效果同 and in(set) 在 in 列表中的值,如 in(100, 200),效果同 or like 萬用字元 模糊查詢:% 匹配多個字元,如 first_name like "a%";_ 匹配一個字元,如 first_name like "a_"。 is null 為空 is not null 不為空 and 同時成立 or 任一成立 not 不成立,如 where not(salary > 100); 常用聚合查詢條件
統計函式 解釋 count() 求總數 avg() 求平均數 sum() 求和 max() 求最大值 min() 求最小值
1、DML 插入記錄語句
含可空欄位、非空但是含有預設值的欄位、自增欄位,可以不用在 insert 後的欄位列表裡面出現,values 後面只寫對應欄位名稱的 value,這些沒有寫的欄位可以自動設定為 NULL、預設值、自增的下一個數字。
1)插入單條記錄
# 插入單條記錄,插入到指定列 # insert into 表名 (列名1, 列名2, ...) values (值1, 值2, ...); > insert into student (name, age, class) values ("xiao bai", 18, "one"); Query OK, 1 row affected (0.09 sec)
# 插入單條記錄,插入到所有列 # insert into 表名 values (值1, 值2, ...); > insert into student values (2, "li si", 20, 90, "two", "aaaaaaaa"); Query OK, 1 row affected (0.04 sec)
2)插入多條記錄
# 插入多條記錄,插入到指定列 # insert into 表名 (列名1, 列名2, ...) values (值1, 值2, ...), (值1, 值2, ...), ...; > insert into student (name, age, class) values ("zhang san", 18, "one"), ("li si", 19, "one"); Query OK, 2 rows affected (0.03 sec) Records: 2 Duplicates: 0 Warnings: 0
# 插入多條記錄,插入到所有列 # insert into 表名 values (值1, 值2, ...), (值1, 值2, ...), ...; > insert into student values (5, "zhang san", 20, 90, "two", "aaaaaaaa"), (6, "li si", 21, 92, "two", "bbbbbbbb"); Query OK, 2 rows affected (0.08 sec) Records: 2 Duplicates: 0 Warnings: 0
2、DML 刪除記錄語句
- delete 一條一條刪除,不清空 auto_increment 記錄數,truncate 直接將表刪除重建表,清空 auto_increment 記錄數。
不論時單表還是多表,不加 where 條件將會把表的所有記錄刪除。
1)刪除單個表中的記錄
# 刪除單個表中的記錄,刪除所有表記錄 # delete from 表名; > delete from student; Query OK, 5 rows affected (0.08 sec)
# 刪除單個表中的記錄,刪除滿足條件的表記錄 # delete from 表名 where 條件; > delete from student where no = 5; Query OK, 1 row affected (0.11 sec)
# 刪除單個表中的記錄,刪除所有表記錄 # truncate table 表名; > truncate table student; Query OK, 0 rows affected (0.08 sec)
2)刪除多個表中的記錄
# 刪除多個表中的記錄,如果 from 後面的表用別名,delete 後面也要用相應的別名 # delete 表名1, 表名2, ... from 表名1, 表名2, ... [where 條件]; > delete a, b from emp a, dept b where a.dept.no = b.deptno and a.deptno = 3; Query OK, 2 rows affected (0.04 sec)
3、DML 更新記錄語句
1)更新單個表中的記錄
# 更新單個表中的記錄,所有指定列記錄 # update 表名 set 欄位名 = 值, 欄位名 = 值; > update student set age = 18; Query OK, 4 rows affected (0.02 sec) Rows matched: 6 Changed: 4 Warnings: 0
# 更新單個表中的記錄,滿足條件的指定列記錄 # update 表名 set 欄位名 = 值, 欄位名 = 值 where 條件; > update student set age = 19 where class = "two"; Query OK, 3 rows affected (0.02 sec) Rows matched: 3 Changed: 3 Warnings: 0
2)更新多個表中的記錄
# 更新多個表中的記錄 # update 表名1, 表名2, ... set 表名1.欄位名1 = 值, 表名1.欄位名2 = 值, 表名2.欄位名1 = 值, 表名2.欄位名2 = 值, ... [where 條件]; > 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.04 sec) Rows matched: 5 Changed: 3 Warnings: 0
- 多表的更新語法更多的用在根據一個表的欄位來動態的更新另外一個表的欄位。
4、DML 查詢記錄語句
4.1 查詢單表記錄
1)簡單查詢
# 查詢單表記錄,查詢所有資料 # select * from 表名; > select * from zhangwu; +----+-----------------+-------+ | id | name | money | +----+-----------------+-------+ | 1 | chifanzhichu | 247 | | 2 | gongzishouru | 12345 | | 3 | fuzhuangzhichu | 1000 | | 4 | chifanzhichu | 325 | | 5 | gupiaoshouru | 8000 | | 6 | damajiangzhichu | 8000 | | 7 | NULL | 5000 | +----+-----------------+-------+ 7 rows in set (0.00 sec)
# 查詢單表記錄,查詢指定欄位記錄 # select 欄位1, 欄位2, ... from 表名; > select id, name from zhangwu; +----+-----------------+ | id | name | +----+-----------------+ | 1 | chifanzhichu | | 2 | gongzishouru | | 3 | fuzhuangzhichu | | 4 | chifanzhichu | | 5 | gupiaoshouru | | 6 | damajiangzhichu | | 7 | NULL | +----+-----------------+ 7 rows in set (0.00 sec)
2)去重查詢
# 查詢單表記錄,去除重複記錄 # select distinct 欄位名 from 表名; > select distinct money from zhangwu; +-------+ | money | +-------+ | 247 | | 12345 | | 1000 | | 325 | | 8000 | | 5000 | +-------+ 6 rows in set (0.00 sec)
3)條件查詢
# 查詢單表記錄,查詢所有滿足條件的記錄 # select * from 表名 where 條件; > select * from zhangwu where money >= 8000; +----+-----------------+-------+ | id | name | money | +----+-----------------+-------+ | 2 | gongzishouru | 12345 | | 5 | gupiaoshouru | 8000 | | 6 | damajiangzhichu | 8000 | +----+-----------------+-------+ 3 rows in set (0.00 sec)
4)別名查詢
- 使用 as 關鍵字標示別名,可省略。
# 查詢單表記錄,表別名查詢 # select 欄位名 from 表名 [as] 別名; > select name from zhangwu as zw; +-----------------+ | name | +-----------------+ | chifanzhichu | | gongzishouru | | fuzhuangzhichu | | chifanzhichu | | gupiaoshouru | | damajiangzhichu | | NULL | +-----------------+ 7 rows in set (0.00 sec)
# 查詢單表記錄,列別名查詢 # select 欄位名 [as] 別名 from 表名; > select name as na from zhangwu; +-----------------+ | na | +-----------------+ | chifanzhichu | | gongzishouru | | fuzhuangzhichu | | chifanzhichu | | gupiaoshouru | | damajiangzhichu | | NULL | +-----------------+ 7 rows in set (0.00 sec)
5)列運算查詢
- 可以直接對列查詢的結果進行運算。
# 查詢單表記錄,列運算查詢 # select 欄位名(列運算) from 表名; > select money + 10000 from zhangwu; +---------------+ | money + 10000 | +---------------+ | 10247 | | 22345 | | 11000 | | 10325 | | 18000 | | 18000 | | 15000 | +---------------+ 7 rows in set (0.00 sec)
6)排序查詢
- 排序方式:asc 升序(預設,可省略),desc 降序,排序需放在 where 條件之後。
# 查詢單表記錄,單列排序查詢 # select 欄位名 from 表名 [where 條件] order by 列名 排序方式; > select * from zhangwu where money > 1000 order by money asc; +----+-----------------+-------+ | id | name | money | +----+-----------------+-------+ | 7 | NULL | 5000 | | 5 | gupiaoshouru | 8000 | | 6 | damajiangzhichu | 8000 | | 2 | gongzishouru | 12345 | +----+-----------------+-------+ 4 rows in set (0.00 sec)
# 查詢單表記錄,多列排序查詢 # select 欄位名 from 表名 [where 條件] order by 列名 排序方式, 列名 排序方式, ...; > select * from zhangwu where money > 1000 order by money asc, id desc; +----+-----------------+-------+ | id | name | money | +----+-----------------+-------+ | 7 | NULL | 5000 | | 6 | damajiangzhichu | 8000 | | 5 | gupiaoshouru | 8000 | | 2 | gongzishouru | 12345 | +----+-----------------+-------+ 4 rows in set (0.00 sec)
7)限制查詢
- limit:只獲取查詢結果中從起始偏移量開始的指定行數的記錄。
- limit 屬於 MySQL 擴充套件後的語法,在其它資料庫上並不能通用。
# 查詢單表記錄,限制查詢 # select 欄位名 from 表名 [where 條件] [order by 列名 排序方式] limit [起始偏移量] 獲取的行數 > select * from zhangwu where money > 1000 order by money asc, id desc limit 3; +----+-----------------+-------+ | id | name | money | +----+-----------------+-------+ | 7 | NULL | 5000 | | 6 | damajiangzhichu | 8000 | | 5 | gupiaoshouru | 8000 | +----+-----------------+-------+ 3 rows in set (0.01 sec)
8)聚合查詢
# 查詢單表記錄,求總數、統計 # select count(欄位名) from 表名; > select count(id) from zhangwu; +-----------+ | count(id) | +-----------+ | 7 | +-----------+ 1 row in set (0.00 sec)
# 查詢單表記錄,求和 # select sum(欄位名) from 表名; > select sum(money) from zhangwu; +------------+ | sum(money) | +------------+ | 34917 | +------------+ 1 row in set (0.00 sec)
# 查詢單表記錄,求平均數 # select avg(欄位名) from 表名; > select avg(money) from zhangwu; +-------------------+ | avg(money) | +-------------------+ | 4988.142857142857 | +-------------------+ 1 row in set (0.00 sec)
# 查詢單表記錄,求最大值 # select max(欄位名) from 表名; > select max(money) from zhangwu; +------------+ | max(money) | +------------+ | 12345 | +------------+ 1 row in set (0.01 sec)
# 查詢單表記錄,求最小值 # select min(欄位名) from 表名; > select min(money) from zhangwu; +------------+ | min(money) | +------------+ | 247 | +------------+ 1 row in set (0.00 sec)
9)分組查詢
- having 是對分組後的結果進行條件過濾,而 where 是在分組前就對記錄進行過濾。
- 如果邏輯允許,儘可能的使用 where 先過濾記錄,因為這樣結果集減小,將對聚合的效率大大提高,最後再根據邏輯看是否用 having 進行再過濾。
# 查詢單表記錄,分組查詢 # select 欄位名 from 表名 [where 條件] group by 分組欄位名 [order by 排序欄位名 排序方式]; > select class, count(no), avg(score) from student group by class; +-------+-----------+------------+ | class | count(no) | avg(score) | +-------+-----------+------------+ | one | 3 | 81.6667 | | two | 2 | 77.5000 | | three | 2 | 83.0000 | +-------+-----------+------------+ 3 rows in set (0.00 sec)
# 查詢單表記錄,分組後過濾查詢 # select 欄位名 from 表名 [where 條件] group by 分組欄位名 having 分組後的過濾條件 [order by 排序欄位名 排序方式]; > select class, count(no), avg(score) from student group by class having avg(score) >= 80; +-------+-----------+------------+ | class | count(no) | avg(score) | +-------+-----------+------------+ | one | 3 | 81.6667 | | three | 2 | 83.0000 | +-------+-----------+------------+ 2 rows in set (0.00 sec)
# 查詢單表記錄,分組後彙總查詢,對分類後的結果進行再彙總 # select 欄位名 from 表名 [where 條件] group by 分組欄位名 with rollup [order by 排序欄位名 排序方式]; > select class, count(no), avg(score) from student group by class with rollup; +-------+-----------+------------+ | class | count(no) | avg(score) | +-------+-----------+------------+ | one | 3 | 81.6667 | | three | 2 | 77.5000 | | two | 2 | 83.0000 | | NULL | 7 | 242.1667 | +-------+-----------+------------+ 4 rows in set (0.00 sec)
10)子查詢
- 某些情況下,當進行查詢的時候,需要的條件是另外一個 select 語句的結果,這個時候,就要用到子查詢。
- 用於子查詢的關鍵字主要包括 in、not in、=、!=、exists、not exists、any、all 等。
- 子查詢,理論上可以出現在任意位置,在 where 和 from 子句中較多。
where 子查詢一般返回單行單列、單行多列、多行單列(in、any、all)的資料,from 子查詢一般返回多行多列的資料。
where 子查詢
# 查詢單表記錄,where 單行單列子查詢 # select 欄位名 from 表名 where 條件(子查詢語句); > select * from student where score > (select score from student where name = "xiao bai" ) order by score asc; +----+-----------+------+-------+-------+----------+ | no | name | age | score | class | address | +----+-----------+------+-------+-------+----------+ | 1 | xiao hei | 18 | 80 | one | NULL | | 6 | li si | 19 | 80 | two | bbbbbbbb | | 3 | zhang san | 18 | 95 | one | NULL | +----+-----------+------+-------+-------+----------+ 3 rows in set (0.00 sec)
# 查詢單表記錄,where 單行多列子查詢 # select 欄位名 from 表名 where 條件(子查詢語句); > select * from student where (age, class) = (select age, class from student where name = "zhang san" ) order by score asc; +----+-----------+------+-------+-------+---------+ | no | name | age | score | class | address | +----+-----------+------+-------+-------+---------+ | 1 | xiao hei | 18 | 80 | one | NULL | | 3 | zhang san | 18 | 95 | one | NULL | | 4 | wang wu | 18 | 70 | one | NULL | +----+-----------+------+-------+-------+---------+ 3 rows in set (0.00 sec)
- where in 子查詢
# 查詢單表記錄,where 多行單列 in 子查詢,與普通的 in 條件類似,如果子查詢記錄數唯一,還可以使用 = 代替 in # select 欄位名 from 表名 where 條件(in 子查詢語句); > select * from student where age in (select age from student where class = "one" ) order by age asc; +----+-----------+------+-------+-------+----------+ | no | name | age | score | class | address | +----+-----------+------+-------+-------+----------+ | 4 | wang wu | 18 | 70 | one | NULL | | 1 | xiao hei | 18 | 80 | one | NULL | | 3 | zhang san | 19 | 95 | one | NULL | | 6 | li si | 19 | 80 | two | bbbbbbbb | | 7 | xiao bai | 19 | 79 | three | NULL | | 2 | da bai | 19 | 75 | two | aaaaaaaa | +----+-----------+------+-------+-------+----------+ 6 rows in set (0.00 sec)
- where any 子查詢
# 查詢單表記錄,where 多行單列 =any 子查詢,與 in 子查詢一樣 # select 欄位名 from 表名 where 條件(=any 子查詢語句); > select * from student where age = any (select age from student where class = "one" ) order by age asc; +----+-----------+------+-------+-------+----------+ | no | name | age | score | class | address | +----+-----------+------+-------+-------+----------+ | 4 | wang wu | 18 | 70 | one | NULL | | 1 | xiao hei | 18 | 80 | one | NULL | | 3 | zhang san | 19 | 95 | one | NULL | | 6 | li si | 19 | 80 | two | bbbbbbbb | | 7 | xiao bai | 19 | 79 | three | NULL | | 2 | da bai | 19 | 75 | two | aaaaaaaa | +----+-----------+------+-------+-------+----------+ 6 rows in set (0.01 sec)
# 查詢單表記錄,where 多行單列 >any 子查詢,大於最小值 # select 欄位名 from 表名 where 條件(>any 子查詢語句); > select * from student where age > any (select age from student where class = "one" ) order by age asc; +----+-----------+------+-------+-------+----------+ | no | name | age | score | class | address | +----+-----------+------+-------+-------+----------+ | 2 | da bai | 19 | 75 | two | aaaaaaaa | | 3 | zhang san | 19 | 95 | one | NULL | | 6 | li si | 19 | 80 | two | bbbbbbbb | | 7 | xiao bai | 19 | 79 | three | NULL | | 5 | ma liu | 20 | 78 | three | NULL | +----+-----------+------+-------+-------+----------+ 5 rows in set (0.00 sec)
# 查詢單表記錄,where 多行單列 <any 子查詢,小於最大值 # select 欄位名 from 表名 where 條件(<any 子查詢語句); > select * from student where age < any (select age from student where class = "one" ) order by age asc; +----+----------+------+-------+-------+---------+ | no | name | age | score | class | address | +----+----------+------+-------+-------+---------+ | 1 | xiao hei | 18 | 80 | one | NULL | | 4 | wang wu | 18 | 70 | one | NULL | +----+----------+------+-------+-------+---------+ 2 rows in set (0.00 sec)
- where all 子查詢
# 查詢單表記錄,where 多行單列 >all 子查詢,大於最大值 # select 欄位名 from 表名 where 條件(>all 子查詢語句); > select * from student where age > all (select age from student where class = "one" ) order by age asc; +----+--------+------+-------+-------+---------+ | no | name | age | score | class | address | +----+--------+------+-------+-------+---------+ | 5 | ma liu | 20 | 78 | three | NULL | +----+--------+------+-------+-------+---------+ 1 row in set (0.00 sec)
# 查詢單表記錄,where 多行單列 <all 子查詢,小於最小值 # select 欄位名 from 表名 where 條件(<all 子查詢語句); > select * from student where age < all (select age from student where class = "one" ) order by age asc; +----+----------+------+-------+-------+---------+ | no | name | age | score | class | address | +----+----------+------+-------+-------+---------+ | 7 | xiao bai | 17 | 79 | three | NULL | +----+----------+------+-------+-------+---------+ 1 row in set (0.00 sec)
- from 子查詢
# 查詢單表記錄,from 多行多列子查詢,一般當作一張臨時表的方式來處理 # select 欄位名 from 表名1 內/外連線表子查詢語句; > select B.bno, B.bname, B.bano, C.aname from B, ( select ano, aname, loc from A where ano < 2 ) C where B.bano = C.ano; +-----+----------+------+-----------+ | bno | bname | bano | aname | +-----+----------+------+-----------+ | 0 | zhangsan | 0 | 研發部 | +-----+----------+------+-----------+ 1 row in set (0.00 sec)
4.2 查詢多表記錄
- 當需要同時顯示多個表中的欄位時,就可以用表連線來實現這樣的功能。
從大體上分,表連線分為內連線和外連線,它們之間最主要的區別是,內連線僅選出兩張表中互相匹配的記錄,而外連線會選出其它不匹配的記錄。
1)多表聯合查詢
# 查詢多表記錄,多表聯合查詢,一定要有表於表之間的關聯欄位 # select 欄位名 from 表名1, 表名2 where 關聯條件; > select B.bno, B.bname, B.bano, A.aname from B, A where B.bano = A.ano; +-----+----------+------+-----------+ | bno | bname | bano | aname | +-----+----------+------+-----------+ | 0 | zhangsan | 0 | 研發部 | | 1 | lisi | 2 | 銷售部 | +-----+----------+------+-----------+ 2 rows in set (0.00 sec)
2)內聯查詢
# 查詢多表記錄,內連線查詢 # select 欄位名 from 表名1 inner join 表名2 on 關聯條件; > select B.bno, B.bname, B.bano, A.aname from B inner join A on B.bano = A.ano; +-----+----------+------+-----------+ | bno | bname | bano | aname | +-----+----------+------+-----------+ | 0 | zhangsan | 0 | 研發部 | | 1 | lisi | 2 | 銷售部 | +-----+----------+------+-----------+ 2 rows in set (0.00 sec)
3)外聯查詢
# 查詢多表記錄,左外連線查詢,包含所有的左表中的記錄甚至是右表中沒有和它匹配的記錄 # select 欄位名 from 表名1 left outer join 表名2 on 關聯條件; > select B.bno, B.bname, B.bano, A.aname from B left outer join A on B.bano = A.ano; +-----+----------+------+-----------+ | bno | bname | bano | aname | +-----+----------+------+-----------+ | 0 | zhangsan | 0 | 研發部 | | 1 | lisi | 2 | 銷售部 | | 2 | wangwu | NULL | NULL | +-----+----------+------+-----------+ 3 rows in set (0.00 sec)
# 查詢多表記錄,右外連線查詢,包含所有的右表中的記錄甚至是左表中沒有和它匹配的記錄 # select 欄位名 from 表名1 left outer join 表名2 on 關聯條件; > select B.bno, B.bname, B.bano, A.aname from B right outer join A on B.bano = A.ano order by bno asc; +------+----------+------+-----------+ | bno | bname | bano | aname | +------+----------+------+-----------+ | NULL | NULL | NULL | 財務部 | | 0 | zhangsan | 0 | 研發部 | | 1 | lisi | 2 | 銷售部 | +------+----------+------+-----------+ 3 rows in set (0.00 sec)
# 查詢多表記錄,全外連線查詢,包含所有的左表和右表中的記錄甚至是沒有匹配的記錄 # MySQL 是不支援全外的連線的,這裡給出的寫法適合 Oracle 和 DB2 # select 欄位名 from 表名1 left outer join 表名2 on 關聯條件; > select B.bno, B.bname, B.bano, A.aname from B full outer join A on B.bano = A.ano order by bno asc;
4)記錄聯合查詢
- 我們經常會碰到這樣的應用,將兩個表的資料按照一定的查詢條件查詢出來後,將結果合併到一起顯示出來。
- 這個時候,就需要用 union 和 union all 關鍵字來實現這樣的功能。
- union all 會把結果直接合並在一起,union 會將合併後的結果進行一次 distinct 去除重複的記錄。
# 查詢多表記錄,記錄聯合查詢 # select 欄位名 from 表名1 union | union all select 欄位名 from 表名2; > select ano, aname, loc from A union all select bno, bname, bano from B; +-----+-----------+------+ | ano | aname | loc | +-----+-----------+------+ | 0 | 研發部 | aaaa | | 1 | 財務部 | bbbb | | 2 | 銷售部 | cccc | | 0 | zhangsan | 0 | | 1 | lisi | 2 | | 2 | wangwu | NULL | +-----+-----------+------+ 6 rows in set (0.00 sec)