MySQL DML
添加数据
添加数据,使用关键词INSERT INTO
语法为:
INSERT INTO 表名 (列1,列2,列3) VALUES (值1,值2,值3);
如果需要一次创建多条记录,则为:
INSERT INTO 表名 (列1, 列2, 列3) VALUES (值1, 值2, 值3);
比如:
sql
INSERT INTO `student` (`name`, `age`, `grade_id`) VALUES
('张三', 18, 1),
('李四', 17, 1),
('王五', 19, 2),
('赵六', 18, 2),
('钱七', 17, 3),
('孙八', 20, 3),
('周九', 18, 1),
('吴十', 19, 2),
('郑十一', 17, 3),
('王十二', 18, 4);
自增长的列无需添加值,数据会自动增长。未添加的列,会根据列的配置,显示默认值。
修改数据
修改数据,使用关键词UPDATE
语法为:
UPDATE 表名 SET 列名=值1,列名=值2,...
WHERE 条件
比如:
sql
UPDATE `student`
SET `name`='李白', `age`=3
WHERE `id`=5;
注意:没有设置WHERE条件的UPDATE会更新所有行!
删除数据
删除数据,使用关键词DELETE FROM
语法为:
DELETE FROM 表名
WHERE 条件
比如:
sql
DELETE FROM `student`
WHERE `id`=5;
删除数据还可以使用TRUNCATE命令,专门用来删除表数据。
与DELETE命令区别在于:
- 速度更快
- 可以重置表的自增字段。通过DELETE删除数据后,新增数据的列的还是会自动增量。
比如:
sql
TRUNCATE TABLE `student`
MySQL DQL
查询数据
查询数据,使用关键词SELECT
语法为:
SELECT 字段,...
FROM 表名
如果要重命名字段名,可以使用AS
比如:
sql
SELECT `emp_id` AS '员工id', `emp_name` AS '员工名'
FROM `employees`
如果查询全部字段,可以使用符号*
sql
SELECT *
FROM `employees`
数据去重
使用关键词DISTINCT去除重复数据
比如:
sql
SELECT DISTINCT `emp_id` FROM `employee_projects`
where条件
作用:检索满足where条件的行,where后接结果为布尔值的条件表达式,支持逻辑运算符。
逻辑运算符
| 逻辑运算符 | SQL常用替换语法 | 描述 | 解释 |
|---|---|---|---|
| && | AND | 逻辑且,只有两者为真才为真 | 且 |
| || | OR | 逻辑或,两者有一为真即为真 | 或 |
| ! | NOT | 逻辑非,取反 | 非 |
WHERE后既可以用逻辑运算符,也可以用替换的语法,比如:
sql
SELECT *
FROM `employees`
WHERE `salary`>10000.00 AND `salary`<12000.00
等价于
sql
SELECT *
FROM `employees`
WHERE `salary`>10000.00 && `salary`<12000.00
模糊查询:比较运算符
| 运算符 | 语法 | 描述 |
|---|---|---|
| IS NULL | a IS NULL | 列a为NULL,则为真 |
| IS NOT NULL | a IS NOT NULL | 列a不为NULL,则为真 |
| BETWEEN AND | a ETWEEN b AND c | 如果a在b和c之间,则为真 |
| LIKE | a LIKE b | SQL匹配,如果a匹配b,则为真。(使用%符号代表多个字符,使用_符号代表1个字符): - % 代表 零个或多个 字符(不只是"多个")。 - _ 代表 恰好一个 字符。 - 例如:LIKE '张%' 可以匹配 "张"、"张三"、"张三丰"。 |
| IN | a IN (b,c,d) | 若a等于b/c/d中的任一值,则为真 |
示例:
sql
SELECT *
FROM `employees`
WHERE `salary` IS NULL
sql
SELECT *
FROM `employees`
WHERE `salary` BETWEEN 8000 AND 12000
-- 等价于 WHERE `salary` >= 8000 AND `salary` <= 12000
sql
SELECT *
FROM `employees`
WHERE `emp_name` LIKE '张%'
-- 查询emp_name满足:张开头的字符串
sql
SELECT *
FROM `employees`
WHERE `salary` IN (8000, 9000)
-- 等价于 WHERE `salary` = 8000 OR `salary` = 9000
联表查询
联表查询,使用关键词JOIN...ON。
两个表联表查询,有LEFT JOIN(左联)、RIGHT JOIN(右链)、INNER JOIN(内联)三种join方式,而又可以根据要查询内容的范围,细分出7种查询方式。
LEFT JOIN
LEFT JOIN左连查询,就是把按照左表为主进行查询,查询出所有左表已有的记录。当右表没有这条记录时,填充NULL。
假设有两个表:学生表和班级表,学生表和班级表通过班级id做关联
学生表如下。注意:学生"张三"没有class_id,没有办法通过班级表查询到班级信息。而班级表额外有个class_id为3的记录行,而学生表没有class_id为3的学生
| student_id | student_name | class_id |
|---|---|---|
| 1 | 张三 | NULL |
| 2 | 李四 | 1 |
| 3 | 王五 | 2 |
| 4 | 赵六 | 2 |
班级表如下:
| class_id | class_name |
|---|---|
| 1 | 1班 |
| 2 | 2班 |
| 3 | 3班 |
通过LEFT JOIN查询,将学生表作为左表:
sql
SELECT *
FROM `student` AS s
LEFT JOIN `class` AS c
ON s.`class_id`=c.`class_id`
查询结果如下,其中s.class_id表示是学生表中的班级id,c.class_id是班级表中的班级id。
| s.student_id | s.student_name | s.class_id | c.class_id | c.class_name |
|---|---|---|---|---|
| 1 | 张三 | NULL | NULL | NULL |
| 2 | 李四 | 1 | 1 | 1班 |
| 3 | 王五 | 2 | 2 | 2班 |
| 4 | 赵六 | 2 | 2 | 2班 |
| 从查询结果可以看出,LEFT JOIN查询出了左表的所有行。当左表中的记录在右表没有记录时,右表的字段显示NULL。 |
RIGHT JOIN
RIGHT JOIN与LEFT JOIN逻辑几乎相同,只不过是以右表作为主表进行查询,即查询出右表的所有记录(只是字段顺序可能不同)。当右表在左表中没有记录时,填充NULL。
sql
SELECT *
FROM `class` AS c
RIGHT JOIN `student` AS s
ON s.`class_id`=c.`class_id`
-- 等同于
-- SELECT *
-- FROM `student` AS s
-- LEFT JOIN `class` AS c
-- ON s.`class_id`=c.`class_id`
| c.class_id | c.class_nam | s.student_id | s.student_name | s.class_id |
|---|---|---|---|---|
| NULL | NULL | 1 | 张三 | NULL |
| 1 | 1班 | 2 | 李四 | 1 |
| 2 | 2班 | 3 | 王五 | 2 |
| 2 | 2班 | 4 | 赵六 | 2 |
INNER JOIN
INNER JOIN联表查询,将两个表都有并且条件相同记录查询出来,如上述学生表和班级表INNER JOIN联表查询结果如下:
| s.student_id | s.student_name | s.class_id | c.class_id | c.class_name |
|---|---|---|---|---|
| 2 | 李四 | 1 | 1 | 1班 |
| 3 | 王五 | 2 | 2 | 2班 |
| 4 | 赵六 | 2 | 2 | 2班 |
| 从查询结果来看,仅展示了学生表中class_id在班级表中class_id同时存在的记录。 |
自连接
某些表内关联自身,比如下方的分类表,父类别parent_id为category_id。
| category_id | parent_id | category_name |
|---|---|---|
| 1 | NULL | 电子产品 |
| 2 | NULL | 服装服饰 |
| 3 | 1 | 手机 |
| 4 | 1 | 电脑 |
| 5 | 2 | 男装 |
| 6 | 2 | 女装 |
| 此时,如果要求查询出所有分类的父分类名称,比如: |
| category_id | category_name | parent_category_name |
|---|---|---|
| 1 | 电子产品 | NULL |
| 2 | 服装服饰 | NULL |
| 3 | 手机 | 电子产品 |
| 4 | 电脑 | 电子产品 |
| 5 | 男装 | 服装服饰 |
| 6 | 女装 | 服装服饰 |
| 则需要把这个表连接表自身进行联表查询,这种叫做自连接。 |
sql
SELECT a.`category_id` AS '分类id', a.`category_name` AS '分类名称', b.`category_name` AS '父分类名称'
FROM `category` AS a
LEFT JOIN `category` AS b
ON a.`parent_id`=b.`category_id`;
排序和分页
排序
对查询结果集排序使用关键词:ORDER BY,语法为:
ORDER BY 字段名 ASC(上升)/DESC(下降):
- ASC
- 全称:Ascending(上升)
- 含义:从小到大、从A到Z、从早到晚排序
- DESC
- 全称:Descending(下降)
- 含义:从大到小、从Z到A、从晚到早排序
比如:
sql
SELECT *
FROM `order_details`
ORDER BY `product_name` ASC
分页
对查询结果集分页,使用关键词:LIMIT,语法为:
LIMIT 分页开始的索引,分页的数量
比如:
SELECT *
FROM `order_details`
ORDER BY `product_name` ASC
LIMIT 3,3
-- 代表从第三条记录(包含)开始,一共返回3条记录
也可以不填写分页开始的索引,LIMIT后跟分页的数量,比如:
sql
SELECT *
FROM `order_details`
ORDER BY `product_name` ASC
LIMIT 3
-- 等价于LIMIT 0,3
在开发过程中,一般需要分页查询数据,而分页传参一般包括:每页的数量(Size)、第几页(SizeNum),对应到SQL中的分页查询语法为:
LIMT (SizeNum-1)*Size, Size
子查询
SQL支持子查询,又称嵌套查询,是指在一个SQL查询内部嵌套另一个完整的SELECT查询。子查询可以嵌套在WHERE、FROM、SELECT、HAVING等子句中,必须用括号()包裹。系统会先执行内层查询,再执行外层查询。
假设有两个表:学生表和班级表
| student_id | student_name | class_id |
|---|---|---|
| 1 | 张三 | NULL |
| 2 | 李四 | 1 |
| 3 | 王五 | 2 |
| 4 | 赵六 | 2 |
| class_id | class_name |
|---|---|
| 1 | 1班 |
| 2 | 2班 |
| 3 | 3班 |
| 假如有个需求:找出已经分配了班级的学生,则可以用子查询查出所有的班级id,然后用IN关键词过滤,比如: |
sql
SELECT *
FROM `student` AS s
WHERE `class_id` IN (
SELECT `class_id`
FROM `class`
)
MySQL常用函数
MYSQL支持很多函数,比如数学运算:计算绝对值、向上取整、向下取整等。支持很多字符串函数:比如计算字符串长度、合并字符串、查询替换、转大写、转小写等
MySQL聚合函数
| 函数名称 | 描述 |
|---|---|
| COUNT() | 计数 |
| SUM() | 求和 |
| AVG() | 平均值 |
| MAX() | 最大值 |
| MIN() | 最小值 |
| ... | ... |
| 比如: |
sql
SELECT SUM(`unit_price`)
FROM `order_details`
使用关键词GROUP BY分组,语法为
GROUP BY 查询结果集的字段
之后还可以接HAVING,对分组后的结果进行条件过滤
比如:
sql
SELECT `product_name`, SUM(`quantity`) AS totoal_quantity
FROM `order_details`
WHERE `product_name` NOT IN ('服务器', '显示器')
GROUP BY `product_name`
HAVING totoal_quantity >= 2
WHERE和HAVING都能做条件判断,区别在于:
- HAVING必须接在GROUP BY后
- HAVING对分组后的结果进行过滤,而WHERE在分组前进行过滤
DQL总结
SQL SELECT语句总结:
sql
SELECT [ALL | DISTINCE] 字段名
FROM [表名 | (子查询结果集)]
XXX JOIN [表名 | (子查询结果集)]
ON 联表查询等值
WHERE 过滤条件
GROUP BY 分组条件
HAVING 分组后过滤条件
ORDER BY 排序字段 ASC或DESC
LIMIT (分页起始索引,页内数据长度)