一、DQL查询语句进阶
排序查询:
ORDER BY 排序字段1 排序方式1,排序字段2 排序方式2,…排序字段n 排序方式n;
SELECT * FROM STUDENT3 ORDER BY math DESC -- 排序方式:没写默认ASC(升序);DESC(降序)
SELECT *FROM STUDENT3 ORDER BY math ASC,english ASC;-- 按照数学成绩升序排列,如果数学成绩相同则按英语成绩升序排列
注意:如果有多个排序条件,则当前的条件值一样时,才会判断第二条件
聚合函数:将一列数据作为一个整体,进行纵向的计算
SELECT COUNT(NAME) FROM STUDENT3;#计算个数count
SELECT MAX(math) FROM STUDENT3;#获取最大值max
SELECT MIN(IFNULL(english,0))AS 英语最小值 FROM STUDENT3 ;#获取最小值min
SELECT SUM(math) FROM STUDENT3;#求和sum
SELECT AVG(math) FROM STUDENT3;#计算平均值avg
注意:聚合函数的计算都排除了null值。解决的方法可以使用IFNULL
或者选择不包含空的列(主键)进行计算,甚至使用(*)
分组查询:
GROUP BY 分组字段;#分组之后查询的字段必须为分组字段或聚合函数,写其他的没有意义
-- 按性别分组,分别查男、女同学的平均分
SELECT
sex, COUNT(id) AS 人数 ,AVG(math) AS 数学平均分, AVG(english) AS 英语平均分
FROM
STUDENT3
GROUP BY
sex;
-- 按性别分组,分别查男、女同学的平均分,分数低于70分的不参与分组
SELECT
sex, COUNT(id) AS 人数 ,AVG(math) AS 数学平均分, AVG(english) AS 英语平均分
FROM
STUDENT3
WHERE
math>70 AND english>70
GROUP BY
sex;
-- 按性别分组,分别查男、女同学的平均分,分数低于70分的不参与分组,分组后只显示人数大于一个人的组
SELECT
sex, COUNT(id) AS 人数 ,AVG(math) AS 数学平均分, AVG(english) AS 英语平均分
FROM
STUDENT3
WHERE
math>70 AND english>70
GROUP BY
sex
HAVING
COUNT(id)>1;
Tips:where
和having
的区别:where
在分组之前进行限定,如果不满足条件,则不参与分组。having
在分组之后进行限定,如果不满足结果,则不会被查询出来;where
后不可以跟聚合函数,而having
可以进行聚合函数的判断
分页查询:limit
分页操作是MySQL的一个“方言”
语法:limit 开始的索引,每页查询的条数
-- 每页显示3条记录
-- 公式:开始的索引 = (当前的页码-1)*每页显示的条数
SELECT * FROM STUDENT3 LIMIT 0,3; -- 第一页
二、约束
1)概念:约束是对表中的数据进行限定,保证数据的正确性、有效性和完整性
2)约束的分类:主键约束(primary key)、非空约束(not null)、唯一约束(unique)、外键约束(foreign key)
3)非空约束:某一列的值不能为null
方式一:创建表时添加非空约束
CREATE TABLE STU(
ID INT ,
NAME VARCHAR(20) NOT NULL-- NAME为非空
);
方式二:创建表完后添加非空约束
CREATE TABLE STU(
ID INT ,
NAME VARCHAR(20) -- NAME不为非空
);
ALTER TABLE
STU
MODIFY
NAME VARCHAR(20) NOT NULL;-- 修改NAME为非空
删除非空约束:
ALTER TABLE
STU
MODIFY
NAME VARCHAR(20) -- 删除非空约束
4)唯一约束:unique
,某一列的值不能重复
注意:唯一约束可以有null值,但是只能有一列一条记录为null
方式一:创建表时添加唯一约束
CREATE TABLE STU (
ID INT ,
PHONE_NUMBER VARCHAR(20) UNIQUE
);
方式二:创建表完后添加唯一约束
CREATE TABLE STU (
ID INT ,
PHONE_NUMBER VARCHAR(20)
);
ALTER TABLE
STU
MODIFY
PHONE_NUMBER VARCHAR(20) UNIQUE;#添加唯一约束时,表中不能有重复记录
删除唯一约束:
ALTER TABLE
STU
DROP
INDEX PHONE_NUMBER;
5)主键:primary key
非空且唯一、一张表只能有一个字段为主键
主键就是表中记录的唯一标识,就是必须有的东西
方式一:在创建表时添加主键约束
CREATE TABLE STU(
ID INT PRIMARY KEY, -- 添加主键约束
NAME VARCHAR(20)
);
方式二:创建表完后添加主键约束
CREATE TABLE STU(
id INT,
NAME VARCHAR(20)
);
ALTER TABLE
stu
MODIFY
id INT PRIMARY KEY;
6)主键的自动增长:如果某一列是数值类型的,使用关键字AUTO_INCREMENT可以来完成值的自动增长,一般和主键配合使用
方式一:创建表时,添加主键约束并且完成主键自增长
CREATE TABLE STU(
ID INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20)
);
INSERT INTO STU VALUE(NULL,'CCC');
删除自动增长:
ALTER TABLE
STU
MODIFY
ID INT;
删除主键约束:
ALTER TABLE
STU
DROP PRIMARY KEY; -- 删除主键
7)外键约束:让表与表产生关系,从而保证数据的正确性。一般情况下,外键关联另外一张表的主键
在创建表时,可以添加外键
:CREATE TABLE 表名(
…
外键列
CONSTRAINT 外键名称 foreign key (外键列名) REFERENCES 主表名称(主键名称)
);
CREATE TABLE emp (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(30),
age INT,
dep_name VARCHAR(30),
dep_location VARCHAR(30)
);
-- 添加数据
INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('张三', 20, '研发部', '广州');
INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('李四', 21, '研发部', '广州');
INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('王五', 20, '研发部', '广州');
INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('老王', 20, '销售部', '深圳');
INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('大王', 22, '销售部', '深圳');
INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('小王', 18, '销售部', '深圳');
SELECT * FROM EMP;
-- 数据冗余:数据重复过多,此时需要做表的拆分
-- 一张表专门放员工信息,一张表专门放部门信息
-- 解决方案:分成 2 张表
-- 创建部门表(id,dep_name,dep_location)
-- 一方,主表
CREATE TABLE department(
id INT PRIMARY KEY AUTO_INCREMENT,
dep_name VARCHAR(20),
dep_location VARCHAR(20)
);
-- 创建员工表(id,name,age,dep_id)
-- 多方,从表
CREATE TABLE employee(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
age INT,
dep_id INT ,-- 外键对应主表的主键
CONSTRAINT emp_dept_fk FOREIGN KEY (dep_id) REFERENCES department(id)
)
-- 添加 2 个部门
INSERT INTO department VALUES(NULL, '研发部','广州'),(NULL, '销售部', '深圳');
SELECT * FROM department;
-- 添加员工,dep_id 表示员工所在的部门
INSERT INTO employee (NAME, age, dep_id) VALUES ('张三', 20, 1);
INSERT INTO employee (NAME, age, dep_id) VALUES ('李四', 21, 1);
INSERT INTO employee (NAME, age, dep_id) VALUES ('王五', 20, 1);
INSERT INTO employee (NAME, age, dep_id) VALUES ('老王', 20, 2);
INSERT INTO employee (NAME, age, dep_id) VALUES ('大王', 22, 2);
INSERT INTO employee (NAME, age, dep_id) VALUES ('小王', 18, 2);
SELECT * FROM employee;
8)删除外键:ALTER TABLE employee DROP FOREIGN KEY emp_dept_fk;
9)创建表完之后再添加外键:
ALTER TABLE
employee
ADD CONSTRAINT emp_dept_fk FOREIGN KEY (dep_id) REFERENCES department(id);
10)级联操作
-- 添加外键,设置级联更新,设置级联删除
ALTER TABLE
employee
ADD CONSTRAINT emp_dept_fk FOREIGN KEY (dep_id)
REFERENCES
department(id)
ON UPDATE CASCADE ON DELETE CASCADE;
三、多表之间的关系
1)一对一的关系:如一个人只有一个身份证,一个身份证只能对应一个人
实现:可在任意一方添加外键指向另一方的主键。并让此外键添加唯一约束。
2)一对多(多对一)的关系:如一个部门有多个员工,一个员工只能对应一个部门
实现:在多的一方建立外键,指向一的一方的主键
3)多对多的关系:如一个学生可以选择很多门课程,一个课程也可以被很多学生选择
实现:多对多关系实现需要借助第三张中间表。中间表至少包含两个字段,这两个字段作为第三张表的外键,分别指向两张表的主键
4)案例分析:设计一个数据库,包含表:旅游线路分类、旅游线路、用户,其中分类与线路表是一对多的关系,线路表和用户是多对多的关系
范例:
-- 创建数据库
CREATE DATABASE travel_demo;
-- 进入数据库
USE travel_demo;
-- 建立三个基表
CREATE TABLE classification (
cid INT,
NAME VARCHAR(20)
);
CREATE TABLE routes(
cid INT,
rid INT,
NAME VARCHAR(20),
price DOUBLE(8,2)
);
CREATE TABLE user_ (
id INT,
user_name VARCHAR(20),
PASSWORD VARCHAR(20)
);
-- 将cid设为主键
ALTER TABLE classification MODIFY cid INT PRIMARY KEY;
-- 在routes表里新建外键cid
ALTER TABLE routes ADD CONSTRAINT cid FOREIGN KEY (cid) REFERENCES classification(cid);
-- 新建一个中间表实现多对多的关系
CREATE TABLE temp(
rid INT,
uid INT,
PRIMARY KEY(rid,uid) -- 联合主键
);
-- 将rid、uid设为主键
ALTER TABLE routes MODIFY rid INT PRIMARY KEY;
ALTER TABLE user_ MODIFY id INT PRIMARY KEY;
-- 将rid、uid设为对应的表routes、uesr的外键
ALTER TABLE temp ADD CONSTRAINT rid FOREIGN KEY(rid) REFERENCES routes(rid);
ALTER TABLE temp ADD CONSTRAINT uid FOREIGN KEY(uid) REFERENCES user_(id);
四、数据库设计的范式
1)概念:设计数据库时,需要遵循的一些规范。要遵循后边的范式,必须先遵循前边的所有范式要求。设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范。越高的范式数据库冗余越小。目前数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)、第五范式(5NF,又称为完美范式)。一般情况下遵循前三范式就可以了。
2)分类:
第一范式(1NF):每一列都是不可分割的原子数据项
第二范式(2NF):在1NF的基础上,非码属性必须完全依赖于候选码(在1NF基础上消除非主属性对主码的部分函数依赖),先找出码,完全依赖不用管,其他的部分依赖消除
第三范式(3NF):在2NF基础上,任何非主属性不依赖于其他非主属性(在2NF基础上消除传递依赖),消除传递依赖,只剩下函数依赖,传递依赖变成外键生成一张新表
范式 | 特点 |
---|---|
1NF | 原子性:表中每列不可再拆分。 |
2NF | 不产生局部依赖,一张表只描述一件事情 |
3NF | 不产生传递依赖,表中每一列都直接依赖于主键。而不是通过其它列间接依赖于主键。 |
TIPS:
函数依赖:A–>B,如果通过A属性(属性值)的值,可以确定唯一B属性的值。则称B依赖于A
完全函数依赖:A–>B,如果A是一个属性组,则B属性确定需要依赖于A属性组中所有的属性值
部分函数依赖:A–>B,如果A是一个属性组,则B属性值的确定只需要依赖于A属性组中某一些值即可
传递函数依赖:A–>B, B–>C,如果通过A属性(属性组)的值,可以确定唯一B属性的值,在通过B属性(属性组)的值可以确定唯一属性的值,则称C传递函数依赖于A
码:如果在一张表中,一个属性或属性组,被其他所有属性所完全依赖,则称这个属性(属性值)为该表的码
五、数据库的备份和还原
1)命令行:
备份:mysqldump -u用户名 -p密码 数据库名称 >保存的路径
还原:登录——创建——使用——source 文件路径
2)图形化工具