DQL(条件查询)
条件查询:
使用WHERE 子句,将不满足条件的行过滤掉,WHERE 子句紧随 FROM 子句。
语法:select <结果> from <表名> where <条件>
比较:=, != 或<>, >, <, >=, <=
逻辑运算
and 与
or 或
not 非
(1) 模糊查询
LIKE :是否匹配于一个模式 一般和通配符搭配使用,可以判断字符型数值或数值型.
通配符: % 任意多个字符,包含0个字符 _ 任意单个字符
between and 两者之间,包含临界值;
in 判断某字段的值是否属于in列表中的某一项
IS NULL(为空的)或 IS NOT NULL(不为空的)
UNION(连接):
用的比较多union all是直接连接,取到得是所有值,记录可能有重复 union 是取唯一值,记录没有重复
1、UNION 的语法如下:
[SQL 语句 1]
UNION
[SQL 语句 2]
2、UNION ALL 的语法如下:
[SQL 语句 1]
UNION ALL
[SQL 语句 2]
效率:
UNION和UNION ALL关键字都是将两个结果集合并为一个,但这两者从使用和效率上来说都有所不同。
1、对重复结果的处理:UNION在进行表链接后会筛选掉重复的记录,Union All不会去除重复记录。
2、对排序的处理:Union将会按照字段的顺序进行排序;UNION ALL只是简单的将两个结果合并后就返回。
从效率上说,UNION ALL 要比UNION快很多,所以,如果可以确认合并的两个结果集中不包含重复数据且不需要排序时的话,那么就使用UNION ALL。
排序:
-
查询结果排序,使用 ORDER BY 子句排序 order by 排序列 ASC/DESC
-
asc代表的是升序,desc代表的是降序,如果不写,默认是升序
-
order by子句中可以支持单个字段、多个字段、表达式、函数、别名
数量限制:
-
limit子句:对查询的显示结果限制数目 (sql语句最末尾位置)
-
SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset;
-
SELECT * FROM table LIMIT 5;
-
SELECT * from table LIMIT 0,5;
-
SELECT * FROM table LIMIT 2 OFFSET 3;
-- 查询语法
-- select 结果 from 表名 where 数据条件过滤 group by having order by limit
SELECT * FROM t_student
-- =在where子句后面表示 等于
SELECT * FROM t_student WHERE stu_sex='男'
SELECT * FROM t_student WHERE stu_sex!='男'
SELECT * FROM t_student WHERE stu_sex<>'男'
-- and 多个条件的并列,必须全部成立
SELECT * FROM t_student WHERE stu_score >60 AND stu_sex='女'
-- or 多个条件只要满足一个即可
SELECT * FROM t_student WHERE stu_score >60 OR stu_sex='男'
-- 查询成绩合格的学生 >=60 <=100
SELECT * FROM t_student WHERE stu_score >=60 AND stu_score <=100
-- 列名 BETWEEN 区间开始 and 区间结束 包含60 100
SELECT * FROM t_student WHERE stu_score BETWEEN 60 AND 100
-- 模糊查询
-- like
SELECT * FROM t_student WHERE stu_name='锦涛';
-- 查询姓张的人
-- like '关键字 % _' %匹配多个字符 _只能匹配一个字符
SELECT * FROM t_student WHERE stu_name LIKE'张%';
SELECT * FROM t_student WHERE stu_name LIKE'张_';
SELECT * FROM t_student WHERE stu_name LIKE'%涛';
-- 查询成绩为80和90的学生
-- in(值1 ,值2 ...)
SELECT * FROM t_student WHERE stu_score= 80 OR stu_score=90
SELECT * FROM t_student WHERE stu_score IN(80,90,100)
-- not 不在 不是
SELECT * FROM t_student WHERE stu_score NOT IN(80,90,100)
-- 查询性别不为空
-- is null 为null is not null 不为空
SELECT * FROM t_student WHERE stu_sex IS NULL
SELECT * FROM t_student WHERE stu_sex IS NOT NULL
/*
union 将多个查询结果合并,要求查询出来的列数相同
sql1
union 可以去重复元素,对结果进行排序
sql2
union / union all
*/
SELECT stu_name,stu_num FROM t_student WHERE stu_sex ='女'
UNION
SELECT stu_name,stu_num FROM t_student WHERE stu_sex ='女'
-- union all 只是粗暴的合并
SELECT stu_name,stu_num FROM t_student WHERE stu_sex ='女'
UNION ALL
SELECT stu_name,stu_num FROM t_student WHERE stu_sex ='女'
-- order by 排序
-- 默认使用主键 升序排列
SELECT * FROM t_student
SELECT * FROM t_student ORDER BY stu_score ASC
-- 指定排序
SELECT * FROM t_student ORDER BY stu_score DESC
-- 在条件后面加排序
SELECT * FROM t_student WHERE stu_sex='女' ORDER BY stu_score ASC
-- 行数限制
-- SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset;
-- 提取前三条数据
SELECT * FROM t_student LIMIT 3
-- 查询成绩前俩名的学生 查询前俩条
SELECT * FROM t_student WHERE stu_score>0 ORDER BY stu_score DESC LIMIT 2
-- limit 开始位置(从0开始),数量
SELECT * FROM t_student WHERE stu_score>0 ORDER BY stu_score DESC LIMIT 0,2
-- limit 行数 offset 位置
SELECT * FROM t_student WHERE stu_score>0 ORDER BY stu_score DESC LIMIT 2 OFFSET 0
(2)分组查询
语法:
select 分组函数,列(要求出现在group by的后面)
from 表
[where 筛选条件]
group by 分组的列表
[having 分组后的筛选]
[order by 子句]
注意:查询列表比较特殊,要求是分组函数和group by后出现的字段
分组查询中的筛选条件分为两类:
数据源 源位置 关键字
-
分组前筛选 原始表 group by子句的前面 where
-
分组后筛选 分组后的结果集 group by的后面 having
-- 分组查询 分组 会将相同内容分到同一个组 例如使用性别分组
-- 男 2
-- 女 2
-- select 结果 from 表 gronp by 分组列
-- 统计男生女生各有多少人
SELECT stu_sex,COUNT(*) FROM t_student GROUP BY stu_sex
SELECT stu_sex,MAX(stu_score) FROM t_student GROUP BY stu_sex
-- 添加查询条件
SELECT stu_sex,COUNT(*) c
FROM t_student
WHERE stu_score>0 -- 在分组前对数据进行筛选过滤
GROUP BY stu_sex
ORDER BY c DESC -- 对分组后的结果进行排序
LIMIT 1
-- 查询性别人数大于2的 是哪个性别 对分组后的结果进行筛选过滤
SELECT stu_sex,COUNT(*) c
FROM t_student
WHERE stu_score>0
GROUP BY stu_sex
HAVING c>=2 -- 对分组后的结果进行条件过滤
ORDER BY c DESC
(3)子查询
含义:出现在其他语句中的select语句,称为子查询或内查询;外部的查询语句,称为主查询或
(1)分类:
按子查询出现的位置:
-
select后面:仅仅支持标量子查询
-
from后面:支持表子查询
-
where或having后面:支持标量子查询,列子查询,行子查询(较少)
-
exists后面(相关子查询):支持表子查询
按功能、结果集的行列数不同:
-
标量子查询(结果集只有一行一列)
-
列子查询(结果集只有一列多行)
-
行子查询(结果集有一行多列)
-
表子查询(结果集一般为多行多列)
子查询在SELECT语句内部可以出现SELECT 语句。
语句结果可以作为外部语句中条件子句的一部分,也可以作为外部查询的临时表。
例如:插叙成绩最高的学生信息
-- 子查询:出现在其他语句中的select 语句
-- 其他语句: insert ,update,delete,select
-- 在insert 语句中使用子查询
INSERT INTO t_student(stu_name,stu_sex) SELECT stu_name,stu_sex FROM t_student WHERE stu_num=2
-- 在update 语句中使用子查询 注意查询的结果不能在本张表查询
UPDATE t_student SET stu_name='王珊珊' WHERE stu_num=(SELECT stu_num FROM stu_temp WHERE stu_num=2 )
CREATE TABLE stu_temp(
stu_num INT,
stu_name VARCHAR(10)
)
-- 在select语句中使用子查询
/*
按照子查询结果分为
标量子查询(一行一列)
列子查询(一列多行)
行子查询(一行多列)
表子查询(多行多列)
按子查询出现的位置:
select后面:仅仅支持标量子查询
from后面:支持表子查询
where或having后面:支持标量子查询,列子查询,行子查询(较少)
exists后面(相关子查询):支持表子查询
*/
-- 在select 语句加子查询,只能是标量子查询
SELECT stu_name,(SELECT NOW()),stu_num FROM t_student
-- 表子查询 八查询结果当做一张表处理
SELECT * FROM
(SELECT stu_sex,COUNT(*) c FROM t_student GROUP BY stu_sex)t
WHERE t.c>2
-- 列子查询
SELECT * FROM t_student
WHERE stu_socre IN(SELECT stu_score FROM t_student WHERE stu_score>50)
(4)关联查询–多表设计
数据冗余-----拆分
数据库设计范式
-
为了建立冗余较小、结构合理的数据库,设计数据库时必须遵循一定的规则。在关系型数据库中这种规则就称为范式。范式是符合某一种设计要求的总结。
-
目前关系数据库有5种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。
-
满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多规范要求的称为第二范式(2NF),其余范式以次类推。一般来说,数据库只需满足第三范式(3NF)就行了。
(1)第一范式(确保每列保持原子性) 列不可再分
第一范式是最基本的范式。如果数据库表中的所有字段值都是不可分解的原子值,就说明该 数据库表满足了第一范式。
(2)第二范式
就是要有主键,要求其他字段都依赖于主键。 没有主键就没有唯一性,没有唯一性在集合中就定位不到这行记录,所以要主键。
(3)第三范式
就是要消除传递依赖,方便理解,可以看做是“消除冗余”。
外键:
引用另外一个数据表的某条记录。
外键列类型与主键列类型保持一致
数据表之间的关联/引用关系是依靠具体的主键(primary key)和外键(foreign key)建立起来的。
添加外键约束语法
ALTER TABLE 表名 ADD [CONSTRAINT 约束名] FOREIGN KEY(外键列) REFERENCES 关联表(主键);
删除外键语法
ALTER TABLE 表名 DROP FOREIGN KEY 外键约束名
注意
(1)当主表中没有对应的记录时,不能将记录添加到从表
(2)不能更改主表中的值而导致从表中的记录孤立
(3)从表存在与主表对应的记录,不能从主表中删除该行
(4)删除主表前,先删从表
/*
多表设计
设计表时:先确定存储那类信息,学生表,定义列,数据类型 的约束
学生表
老师表
课程表
需要存储不同的信息(一张表中只能存储一类信息)
学生表
民族,年级
老师表
民族,年级
员工表
编号,姓名,性别,部门编号
部门表
部门编号,部门名称
学生表,年级表,课程表
表与表之间常见的几种关系
一对一关联(例如 一个学生只能对应一个年级)
一对多关联(一个年级对应多个学生)
多对一关联(多个学生对应一个年级)
多对多关联
学生表,
学号,姓名,性别,手机号,年级编号,注册时间
年级表,
年级编号,年级名称,年级介绍
课程表,
课程编号,课程名称,课程介绍
*/
DROP TABLE t_dent;
CREATE TABLE grade(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10),
gdesc VARCHAR(50)
)
CREATE TABLE student(
num INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10),
sex CHAR(1),
phone VARCHAR(11),
grade_id INT,
reg_time DATETIME
)
-- 弱关联关系 表与表之间的关系是人为定义的,表结构中并没有实际联系
-- 强关联关系,给外键添加约束,强制让外键与对应的主键产生关系(外键 对应的都是另一个表中的主键)
-- 修改学生表 把gread_id设置为外键 并添加约束名 指定gread_id与gread表中的id列对应
ALTER TABLE student ADD CONSTRAINT grade_id_fk FOREIGN KEY (grade_id) REFERENCES grade(id)
-- 多对多关系
-- 学生与课程的关系 一个学生对应多个课程 一个课程对应多个学生
-- 设计一个关系表,来存储多个之间的关系
CREATE TABLE student_course(
id INT PRIMARY KEY AUTO_INCREMENT,
stu_num INT,
NAME VARCHAR(10),
course_id INT,
CONSTRAINT stu_num_fk FOREIGN KEY (stu_num) REFERENCES student(num),
CONSTRAINT course_id_fk FOREIGN KEY (course_id) REFERENCES course(id)
)
ALTER TABLE student_course DROP NAME
CREATE TABLE course(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10),
vdeac VARCHAR(10)
)
(4)关联查询–续
含义:又称多表查询,当查询的字段来自于多个表时,就会用到连接查询
笛卡尔乘积现象:表1有m行,表2有n行,结果=m*n
-
发生原因:没有有效的连接条件
-
如何避免:添加有效的连接条件
按功能分类:
- 内连接
等值连接
非等值连接
自连接
概念:把满足了条件的两张表中的交集数据查询出来
语法:Select 结果 from 表1,表2 where 表1.column1 = 表2.column2
2.外连接
左外连接
语法:select 结果 from 表1 leftjoin 表2 on 表1.column1 = 表2.column2
右外连接
select 结果 from 表1 right join 表2 on 表1.column1 = 表2.column2
交叉连接
-- 笛卡尔乘积
SELECT
*
FROM
student,
grade -- 内连接
-- 等值连接
-- 查询学生信息,学号,姓名,性别,年级名称
SELECT
student.num,
student.name,
student.sex,
grade.name
FROM
student
INNER JOIN grade
ON student.grade_id = grade.id
-- -----------
-- 为表名定义别名,然后通过别名来访问表中的列
SELECT
s.num,
s.name,
s.sex,
s.grade_id,
g.name,
g.id
FROM
student AS s
INNER JOIN grade g
ON s.grade_id = g.id -- on 后面是俩张表关联条件, 与where后面的条件有区别
-- 使用where条件过滤
SELECT
s.num,
s.name,
s.sex,
s.grade_id,
g.name,
g.id
FROM
student s,
grade g
WHERE s.grade_id = g.id
-- 非等值连接
ALTER TABLE student ADD score INT
-- 成绩等级表
CREATE TABLE score_level(
NAME VARCHAR(10),
lower_score INT,
upper_score INT
)
SELECT
s.name,
sl.name
FROM
student s
INNER JOIN score_level sl
ON s.score BETWEEN sl.lower_score
AND sl.upper_score
-- 自连接
CREATE TABLE t_area(
id INT,
NAME VARCHAR(10),
pid INT
)
SELECT * FROM t_area t1 INNER JOIN t_area t2 ON t1.pid=t2.id
-- 外连接
-- 左外连接
ALTER TABLE student ADD CONSTRAINT FOREIGN KEY (grade_id) REFERENCES grade(id)
SELECT * FROM student s LEFT JOIN grade g ON s.grade_id=g.id
-- 右外连接
SELECT * FROM student s RIGHT JOIN grade g ON s.grade_id=g.id
-- 交叉连接
SELECT * FROM student s CROSS JOIN grade g ON s.grade_id=g.id
JOIN score_level sl
ON s.score BETWEEN sl.lower_score
AND sl.upper_score
-- 自连接
CREATE TABLE t_area(
id INT,
NAME VARCHAR(10),
pid INT
)
SELECT * FROM t_area t1 INNER JOIN t_area t2 ON t1.pid=t2.id
```mysql
-- 外连接
-- 左外连接
ALTER TABLE student ADD CONSTRAINT FOREIGN KEY (grade_id) REFERENCES grade(id)
SELECT * FROM student s LEFT JOIN grade g ON s.grade_id=g.id
-- 右外连接
SELECT * FROM student s RIGHT JOIN grade g ON s.grade_id=g.id
-- 交叉连接
SELECT * FROM student s CROSS JOIN grade g ON s.grade_id=g.id