一、入门
(一)一些词汇
schema 模式 → 关于数据库和表的布局及特性的信息
datetype → 数据类型
column
row
primary key → 主键作为唯一标识,不得重复,非空
(二)主键和SQL语句
主键的习惯
- 不更改主键列的值
- 不重用主键的值
- 不在主键中使用可能会更改的值
什么是SQL
SQL是数据库查询语言
二、数据库的基本操作
选择数据库
语句: use db;
返回值:无
查看有哪些数据库
语句:show databases;
返回值:返回可用数据库的一个列表
查看有哪些表
语句:show tables;
返回值:返回可用表的一个列表
其他常用的语句
SHOW STATUS,用于显示广泛的服务器状态信息;SHOW CREATE DATABASE和SHOW CREATE TABLE,分别用来显示创建特定数据库或表的MySQL语句;SHOW GRANTS,用来显示授予用户(所有用户或特定用户)的安全权限;SHOW ERRORS和SHOW WARNINGS,用来显示服务器错误或警告消息。
常见的关键词
DISTINCT:去重
三、排序
单排序
select * from student order by age;
多排序
select * from student order by age, major;
升序和将序
ORDER BY col1 DESC, col2
默认升序ASC,DESC降序
注意
order by 不能处理A和a的排序问题,这个问题取决于数据库系统本身的设置
四、数据过滤
WHERE子句
常见操作符
注意:
- MySQL在执行匹配时默认不区分大小写
BETWEEN AND两边都是闭区间- 空值检查 →
IS NULL
操作符
AND 操作符
WHERE ... AND WHERE ...
OR 操作符
WHERE ... OR WHERE ...
IN操作符
WHERE ... IN (1001, 1002)
IN和OR的区别
其实IN操作符和OR完成的功能是一样的,但是IN操作符1.在语法上更简单、2.速度上更快、3.而且可以嵌套新的查询语句
NOT操作符
取反
五、通配符
LIKE操作符
两个名词:通配符(wildcard)和搜索模式(search pattern)
search pattern一般由字面量和通配符组成
常用的通配符
% : 任意字符包括不匹配,但是注意%不能匹配NULL
_ : 一个字符
使用注意
- 不要过度使用通配符,会导致查询的速度很慢
- 尽量不要将通配符放在匹配模式的前面,同样会导致速度相对变慢
- 注意不要错
六、正则表达式
MySQL的正则表达式是通用的
REGEXP关键字
SELECT * FROM student where item REGEXP '1000'
OR
REGEXP '1000|2000'
转义
匹配一些特殊字符时,要在前面加\\,因为\本身也是特殊字符
比如匹配.,需要使用\\.
空白字符
匹配字符类
匹配多个实体
一个字符中可能有多个匹配的位置
定位符
例子
SELECT * FROM student WHERE major REGEXP '^math'
七、计算字段
什么是计算字段
在SELECT语句查询时计算的字段称为计算字段
字段(field)和列(column)是同一个意思
注意
数据库服务器是知道SELECT语句中的字段是原生的字段,还是计算产生的字段
拼接字段
Concat函数
语法:CONCAT(field1, field2, ...)
RTrim函数
语法:RTrim(field)
含义:删除右边的空格
使用别名
AS关键字
执行计算
SELCET时计算,如SELECT order_id, price*amount AS expanded_price;
SQL支持+、-、*、/
八、数据处理函数
文本处理函数
RTrim()
Upper()等
locate
语法:locate(substr,str)
含义:返回子串 substr 在字符串 str 中第一次出现的位置
日期处理
1. 日期格式
2. 时间处理
3.间隔 INTERVAL
语法:INTERVAL expr unit
间隔值也用于各种时间函数,如DATE_ADD,DATE_SUB,TIMESTAMPADD和TIMESTAMPDIFF
常用的使用
set @dt=str_to_date('2021-6-10', '%Y-%m-%d');
select @dt - interval 1 day; # 返回2021-6-9
select @dt - interval 1 hour;
select @dt - interval 1 second;
# 复合
select @dt - interval '1 00:00:00' DAY_SECOND; # 返回2021-6-9
-
完整的表格
4. 标准化
'2020-01-01 00:00:00'→'%Y-%m-%d %H:%i:%S'
九、汇总数据
聚集函数
AVG()、MAX()、MIN()、COUNT()、SUM()
聚集不同的值
SELECT AVG(DISTINCT salary) FROM emp;
组合聚集数
SELECT COUNT(*) AS num_items,
MIN(prod_price) as price_min,
MAX(prod_price) as price_max
FROM products
十、分组
创建分组
关键字GROUP BY
注意
- 除了聚集语句外,SELECT语句中的所有列必须出现在GROUP BY子句中
- 如果分组列中具有NULL值,则NULL将作为一个分组返回。如果列 中有多行NULL值,它们将分为一组
- GROUP BY子句必须出现在WHERE子句之后,ORDER BY子句之前
例子
SELECT
departmentId,
avg( salary )
FROM
employee
GROUP BY
departmentId
ORDER BY
departmentId;
过滤数据
使用HAVING过滤分组
例子
SELECT
departmentId,
avg( salary )
FROM
employee
GROUP BY
departmentId
HAVING
avg( salary )> 2000
ORDER BY
departmentId;
HAVING和WHERE的区别
Where 是一个约束声明,使用Where来约束来自数据库的数据,Where是在结果返回之前起作用的,且Where中不能使用聚合函数。
Having是一个过滤声明,是在查询返回结果集以后对查询结果进行的过滤操作,在Having中可以使用聚合函数。
在执行顺序上的不同
要明白这一点,我们要明白SQL语句的执行顺序
(8)SELECT (9)DISTINCT (11)<Top Num> <select list>(1)FROM left_table<join_type> JOIN <right_table>(2) ON <join_condition>(4)WHERE <where_condition>(5)GROUP BY > <group_by_list>(6)WITH <CUBE | RollUP>(7)HAVING <having_condition>(10)ORDER BY <order_by_list>
补充连接表时,ON效率比WHERE比WHERE高,因为ON根据条件筛选数据后再生成临时表,而where是在生成临时表后再根据字段过滤数据
十一、子查询
在SELECT语句中,子查询总是从内向外处理
在where中使用子查询
SELECT
cust_id
FROM
orders
WHERE
order_num IN ( # 注意
SELECT # 子查询
order_num
FROM
orderitems
WHERE
prod_id = 'TNT2')
列必须匹配 在WHERE子句中使用子查询(如这里所示),应 该保证SELECT语句具有与WHERE子句中相同数目的列。通常, 子查询将返回单个列并且与单个列匹配,但如果需要也可以 使用多个列。
在from中使用子查询
select name, id
from (
select * from student where age>10
) tmp;
在select中的子查询,作为计算字段的子查询
该查询是在逻辑上最难理解,也是实际使用中比较少使用的
例子
# 作为计算字段的子查询
SELECT
cust_name,
cust_state,
(
SELECT
count(*)
FROM
orders
WHERE
orders.cust_id = customers.cust_id
) AS orders
FROM
customers
ORDER BY
cust_name;
解释:因为子查询中的where依赖父查询的中的customers表,称为**相关子查询。**因此运行的时候,customer每取出一个新的cust_id,orders表就会按where约束得到一个新的汇总值。
注意:
使用作为计算字段的子查询是万不得已的选择,这样的查询方式在逻辑上不易理解,在排除错误时容易发生错误,而且计算的逻辑和SQL本身的逻辑违背
十二、联结表 JOIN
主键和外键
主键是唯一标识一张表中唯一元素的
外键是引用其他表的某列,作为该表的某列的约束
联结
注意联结本身不是物理存在而是数据库在查询时生成的临时表
创建联结的两种方式
-
使用Where创建——sql92
//SQL92 SELECT e.name, d,dname FROM emp e, dept d WHERE e.deptno = d.deptno and ...; -
使用on创建——sql99
SELECTe.name, d,dname FROM emp e join dept d ON e.deptno = d.deptno WHERE...;多表联结时
SELECT e.ename, d.name, s.grade from emp e join dept d # !!! on e.deptno = d.deptno join salgrade s # !!! on e.sal bewteen s.losal and s.hisal
连接方式
- 等值连接
- 区间连接
内连接、外连接和全连接
解释:
内连接:只保留满足约束的联结
外连接:除了保留满足约束的部分,还会保留左(右)表中未在右(左)出现的行。
全连接:保留左右表中所有的未匹配的行,补空值。不常用
注意:区分内外连接的是 right和left关键词 不是inner和outer,可以缺省inner和outer
例子
SELECT e.name, d,dname
from emp e
left outer join dept d
on e.deptno = d.deptno
两种方式的区别:
on比where高效on比where在结构上清晰
笛卡尔积
不使用约束时的结果
使用表别名
使用不同类型的联结
自联结
from后两个相同的表join
select e2.ename, e1.departmentId from
employee e1 join employee e2
on e1.departmentId = e2.departmentId
where e1.ename ='p1';
自然联结
自然联结排除多次出现,使每个列只返回一次。系统不完成这项工作,由你自己完成它。
这一 般是通过对表使用通配符(SELECT *),对所有其他表的列使用明确的子 集来完成的。
十三、组合查询
UNION关键字
(SELECT ...) # 查询1
UNION
(SELECT ...) # 查询2
规则
- 由两个以上的
SELECT子句组成 - UNION两端的查询必须包含相同的列、表达式或函数(顺序不需要相同,MySQL会自动对齐)
- 数据类型必须兼容:类型不必完全相同。DBMS会自动隐式地转换格式
UNION ALL关键字
UNION会自动去重,加上ALL参数后不会自动去重
注意:UNION和多子句Where在一般情况下是可以替换的,具体的效率需要具体问题具体分析,但是UNION ALL是不可以通过多子句Where完成的
UNION排序
放在所有子句的最后