A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 卞建彬 中级黑马   /  2018-10-18 19:46  /  733 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

day03_MySQL约束
一. 单表查询(掌握)
1. 条件查询
1. 基本语法 where 字句后跟条件
2. 运算符
* < > <=>= <>
* BETWEEN 值1 AND 等同于 值2>=值1 and <=值2
* IN(值1, 值2 . . . 值n) 等同于 =值1 OR =值2 OR = 值n
* IS NULL 如果值为NULL, 要使用 ISNULL
* IS NOT NULL 值不为NULL
* AND &&
* OR ||
* NOT !=
* LIKE 模糊查询
2. 排序查询
基本语法: . . . orderby 字段 asc(desc)
order by 排序字段1 排序方式1 排序字段2 排序方式2 ...;
排序方式:
ASC : 升序, 默认的
DESC: 降序
注意事项:
如果有多个排序条件, 则当前面的条件值一样时, 才会去判断第二条件
案例:
-- 按照数学成绩升序排列(默认ASC升序, DESC 降序)
SELECT * FROM stuORDER BY math DESC;
-- 按照数学成绩升序排序, 如果数学成绩一样, 则按照英语成绩排名
SELECT * FROM stuORDER BY math , english;
3. 聚合函数查询
将一列数据作为一个整体, 进行纵向的计算
1. count : 计算个数
1. 一般选择非空的列 : 主键
2. count(*)
-- 查询个数
SELECT COUNT(id)FROM stu;
SELECT COUNT(NAME)FROM stu;
SELECTCOUNT(IFNULL(english,0)) FROM stu;
SELECT COUNT(*)FROM stu; -- 不推荐
2. max : 计算最大值
-- 查询数学成绩最大值/最小值max /min
SELECT MAX(math)FROM stu;
3. min : 计算最小值
4. sum : 计算和
-- 求和
SELECT SUM(math)FROM stu;
5. avg : 计算平均值
-- 求平均数
SELECT AVG(math)FROM stu;
注意事项: 聚合函数的计算, 排除null值
解决方案 :
1. 选择不包含非空的列进行计算
2. IFNULL函数
总结:
1. 聚合函数里面的参数 : 表的字段
2. 聚合函数在进行运算时, null值不会参与运算
3. 聚合函数一般是对 int 类型的进行运算, 其他类型的没有意义
4. 特别在使用 count(字段) 字段一般是主键字段(非空, 唯一)
4. 分组查询
1. 基本语法: group by 分组字段;
select 字段名 [聚合函数] from 表名 [条件判断] group by 分组字段;
分组之后再进行判断
select 字段名 [聚合函数] from 表名 [条件判断] group by 分组字段 [HAVING 聚合函数查询];
2. 注意事项 :
1. 分组之后查询的字段 : 分组字段, 聚合函数
2. where 和 having的区别?
1. where 在分组之前进行限定, 如果不满足条件, 则不参与分组, having 在分组之后进行限定
2. where 后不可以跟聚合函数, having 可以进行聚合函数的判断
3. 总结:
1. 分组字段数据要有共同特点
2. 分组查询时, select 分组字段, 聚合字段 from . . .
3. 查询操作是, 关键字的先后顺序:
select 字段
from 表名
where 分组前条件判断
group by 分组字段
having 分组后的条件判断
order by 排序查询
案例:
-- 分组查询, 按照性别查询(男, 女 分开)平均分, 分别的人数是多少
SELECT sex,AVG(math) FROM stu GROUP BY sex;
-- 分组查询, 按照性别查询(男, 女 分开)平均分, 分别的人数是多少
SELECT sex,AVG(math), COUNT(id) FROM stu GROUP BY sex;
-- 分组查询, 按照性别查询(男, 女 分开)平均分, 分别的人数, 分数低于70分的人不参与分组
SELECT sex,AVG(math), COUNT(id) FROM stu WHERE math > 70 GROUP BY sex;
-- 分组查询, 按照性别查询(男, 女 分开)平均分, 分别的人数, 分数低于70分的人不参与分组, 分组之后人数要大于2个人
SELECT sex,AVG(math), COUNT(id) FROM stu WHERE math > 70 GROUP BY sex HAVING COUNT(id) >2;
5. 分页查询
数据太多, 一次性查询出来后, 展示效果不好, 就是用户的体验不好
分页操作, 不同的数据库分页基本原理不一样
mysql: limit 进行分页, 奇特数据库不能使用limit 进行分页
1. 语法 : limit 开始的索引,每页查询的条数
开始的索引从 0 开始, 表示第一条记录
2. 公式 : 公式 : 开始的索引 = (当前的页码 - 1) * 每页显示的条数
3. 分页操作是一个"方言"
案例:
-- 每页显示3条记录
SELECT * FROM stu LIMIT0,3; -- 第1页
SELECT * FROM stuLIMIT 3,3; -- 第2页
SELECT * FROM stuLIMIT 6,3; -- 第3页
-- 公式 : 开始的索引 = (当前的页码 - 1) * 每页显示的条数
综合案例:
-- 员工表
CREATE TABLE `emp`(
`empno` INT(11)NOT NULL,
`ename`VARCHAR(50) DEFAULT NULL,
`job` VARCHAR(50)DEFAULT NULL,
`mgr` INT(11)DEFAULT NULL,
`hiredate` DATEDEFAULT NULL,
`sal` DECIMAL(7,2)DEFAULT NULL,
`COMM`DECIMAL(7,2) DEFAULT NULL,
`deptno` INT(11)DEFAULT NULL,
PRIMARY KEY(`empno`),
KEY `fk_emp`(`mgr`),
CONSTRAINT`fk_emp` FOREIGN KEY (`mgr`) REFERENCES `emp` (`empno`)
) ENGINE=INNODBDEFAULT CHARSET=utf8;
INSERT INTO empVALUES (1009, '曾阿牛', '董事长', NULL, '2001-11-17', 50000, NULL, 10);
INSERT INTO empVALUES (1004, '刘备', '经理', 1009, '2001-04-02', 29750, NULL, 20);
INSERT INTO empVALUES (1006, '关羽', '经理', 1009, '2001-05-01', 28500, NULL, 30);
INSERT INTO empVALUES (1007, '张飞', '经理', 1009, '2001-09-01', 24500, NULL, 10);
INSERT INTO empVALUES (1008, '诸葛亮', '分析师', 1004, '2007-04-19', 30000, NULL, 20);
INSERT INTO empVALUES (1013, '庞统', '分析师', 1004, '2001-12-03', 30000, NULL, 20);
INSERT INTO empVALUES (1002, '黛绮丝', '销售员', 1006, '2001-02-20', 16000, 3000, 30);
INSERT INTO empVALUES (1003, '殷天正', '销售员', 1006, '2001-02-22', 12500, 5000, 30);
INSERT INTO empVALUES (1005, '谢逊', '销售员', 1006, '2001-09-28', 12500, 14000, 30);
INSERT INTO empVALUES (1010, '韦一笑', '销售员', 1006, '2001-09-08', 15000, 0, 30);
INSERT INTO empVALUES (1012, '程普', '文员', 1006, '2001-12-03', 9500, NULL, 30);
INSERT INTO empVALUES (1014, '黄盖', '文员', 1007, '2002-01-23', 13000, NULL, 10);
INSERT INTO empVALUES (1011, '周泰', '文员', 1008, '2007-05-23', 11000, NULL, 20);
INSERT INTO empVALUES (1001, '甘宁', '文员', 1013, '2000-12-17', 8000, NULL, 20);
-- 用户表
CREATE TABLE`tab_user` (
`id` INT(11)DEFAULT NULL,
`username`VARCHAR(32) DEFAULT NULL,
`address`VARCHAR(32) DEFAULT NULL,
`password`VARCHAR(32) DEFAULT NULL
) ENGINE=INNODBDEFAULT CHARSET=utf8;
INSERT INTO`tab_user`(`id`,`username`,`address`,`password`) VALUES (2,'b','tj','a'),(3,'c','tj','a'),(4,'d','tj','a'),(5,'e','tj','a'),(6,'f','tj','a'),(7,'t','tj','a'),(8,'k','tj','a'),(9,'l','tj','a'),(10,'jack','tj','a'),(11,'船长','tj','a'),(12,'rose','tj','a'),(13,'王琦','tj','a'),(14,'张五','tj','a'),(1,'a','tj','c');
SELECT * FROM emp;-- 查询表
-- 查询 薪水介于 8000到16000之间的员工的姓名 和工作 薪水(两种方式)
SELECT ename, job,sal
FROM emp
WHERE sal>=8000AND sal<=16000;
SELECT ename, job,sal
FROM emp
WHERE sal BETWEEN8000 AND 16000;
-- 查询 受雇日期是 2000-12-17, 2001-02-20的员工的姓名和受雇日期(两种方式)
SELECT ename,hiredate
FROM emp
WHERE hiredate ='2000-12-17' OR hiredate = '2001-02-20';
SELECT ename,hiredate
FROM emp
WHERE hiredate IN('2000-12-17' , '2001-02-20');
-- 查询 工作不是文员的 薪水总和
SELECT SUM(sal)
FROM emp
WHERE job != '文员';
-- 查询受雇日期 早于 2007-05-23的 员工的薪水总和
SELECT SUM(sal) AS员工的薪水总和
FROM emp
WHERE hiredate<= '2007-05-23';
-- 查询 每一种工作的薪水总和
SELECT job,SUM(sal) AS 薪水总和
FROM emp
GROUP BY job;
-- 查询 工作不是文员的 每一种工作的薪水总和
SELECT job,SUM(sal) AS 薪水总和
FROM emp
WHERE job != '文员'
GROUP BY (job);
-- 查询 受雇日期 2007-05-23的 员工, 并且按照部门分组, 查询每个部门的薪水总和
SELECT deptno,SUM(sal) AS 薪水总和
FROM emp
WHERE hiredate<= '2007-05-23'
GROUP BY deptno;
-- 查询 受雇日期 2007-05-23的 员工, 并且按照部门分组, 查询每个部门的薪水总和, 且部门的总薪水大于90000
SELECT deptno,SUM(sal) AS 薪水总和
FROM emp
WHERE hiredate<= '2007-05-23' -- 分组前条件
GROUP BY deptno --分组字段
HAVING SUM(sal)> 90000; -- 分组后条件, 之后分完组后, 才能求每个部门的总薪水
-- 查询 受雇日期 2007-05-23的 员工, 并且按照部门分组, 查询每个部门的薪水总和, 且部门的总薪水大于25000, 最终按照总薪水的大小进行降序排列
SELECT deptno,SUM(sal) AS 薪水总和
FROM emp
WHERE hiredate<= '2007-05-23'
GROUP BY deptno
HAVING SUM(sal)>90000
ORDER BYSUM(sal)DESC; -- 对最终符合条件的数据进行排序
二. 约束(掌握)
1. 概述: 对表中的数据进行限定, 保证数据的的正确性, 有效性和完整性
一种规范(限制), 数据库约束就是对表中的数据进行规范, 让数据具有某种特点
2. 分类:
1. 主键约束 : primary key
2. 非空约束: not null
3. 唯一约束: unique
4. 外键约束: foreign key
* 非空约束: not null
1. 创建表时添加约束
CREATE TABLE stu(
id INT,
NAME VARCHAR(20)NOT NULL
);
2. 创建表完后, 添加非空约束
ALTER TABLE stuMODIFY NAME VARCHAR(20) NOT NULL;
3. 创建表完后, 去除非空约束
ALTER TABLE stuMODIFY NAME VARCHAR(20);
* 唯一约束: unique, 某一列的值不能重复
1. 注意事项:
唯一约束可以有NULL值, 但是只能有一条记录为null
2. 在创建表时, 添加唯一约束
CREATE TABLE stu2(
id INT,
phone_numberVARCHAR(20) UNIQUE -- 添加唯一约束
);
3. 删除唯一约束
ALTER TABLE stu2DROP INDEX phone_number;
4. 在表创建完后, 添加唯一约束
ALTER TABLE stu2MODIFY phone_number VARCHAR(20) UNIQUE;
* 主键约束: primary key
1. 注意事项:
1. 含义: 非空且唯一
2. 一张表只能有一个字段主键
3. 主键就是表中记录的唯一
2. 在创建表时, 添加主键
CREATE TABLE stu3(
id INT PRIMARYKEY,-- 给id添加主键约束
NAME VARCHAR(20)
);
3. -- 删除主键
ALTER TABLE stu3DROP PRIMARY KEY;
4. -- 创建完表后, 添加主键
ALTER TABLE stu3MODIFY id INT PRIMARY KEY;
5. 自动增长:
概念: 如果某一列是数值类型的, 使用 auto_increment 可以来完成值的自动增长
-- 创建表时添加自动增长
CREATE TABLE stu4(
id INT PRIMARY KEYAUTO_INCREMENT,-- 给id添加主键约束
NAME VARCHAR(20)
);
-- 删除自动增长
ALTER TABLE stu4MODIFY id INT;
-- 添加自动增长
ALTER TABLE stu4MODIFY id INT AUTO_INCREMENT;
* 外键约束 :foreign key , 让表与表产生关系, 从而保证数据的正确性
1. 在创建表时, 添加外键
语法:
create table 表名 {
. . .
外键列
constraint 外键名称 foreign key (外键列的名称) references 主表名称(主表列名称)
};
2. 删除外键:
ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;
3. 添加外键:
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称)
4. 外键的特点:
1. 外键的值不能随意写
2. 外键的值引用于另一张表的主键值
3. 外键的值可以为null , 但是为null没有任何意义
5. 外键的设计原则
主表
子表
6. 级联操作 : 只有表与表之间有关联关系, 才能进行级联操作
作用: 当主表的数据发生变化时, 那么字表的数据会级联发生变化
级联操作: 一般情况下, 操作是对修改(update)和删除(delete)
分两种情况:
1. 当主表的数据变化时, 子表的数据保持一致 on update cascade on update cascade
2. 当主表的数据变化时, 子表的数据(外键的数据) 设置为null
语法: on updateset null on delete set null
1. 添加级联操作
语法:ALTER TABLE 表名 ADD CONSTRAINT 外键名称
OREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称) ON UPDATE CASCADE ON DELETE CASCADE ;
2. 分类:
1. 级联更新:ON UPDATE CASCADE
2. 级联删除:ON DELETE CASCADE
三 数据库的设计
多表之间的关系
1. 一对一 : (了解, 很少存在)
如: 人和身份证的关系
分析: 一个人只有一个身份证, 一个身份证只能对应一个人
如: 用户表和 信息表
主表(子表)可以是任意一方
2. 一对多(多对一) :
如: 部门表和 员工表
分析: 一个部门有多个员工, 一个员工只能对应一个部门
主表: 一方表, 这里值的就是部门表
子表: 多方表, 这里指的就是员工表
外键设计在子表里面
3. 多对多: (通俗的来说, 是强化版的一对一)
如: 学生表和 课程表
分析: 一个学生可以选择很多门课程, 一个课程也可以被很多学生选择
主表(子表) 可以是任意一方 (不推荐这样区分和设计外键)
数据库设计的范式
1. 概念: 设计数据库时, 需要遵循的一些规范, 要遵循后边的范式要求, 必须先遵循前边的所有
设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。
2. 分类:
第一范式(1NF):每一列都是不可分割的原子数据项
第二范式(2NF):在1NF的基础上,非码属性必须完全依赖于码(在1NF基础上消除非主属性对主码的部分函数依赖)
几个概念:
函数依赖:A-->B,如果通过A属性(属性组)的值,可以确定唯一B属性的值。则称B依赖于A
例如:学号-->姓名。(学号,课程名称) --> 分数
完全函数依赖:A-->B,如果A是一个属性组,则B属性值得确定需要依赖于A属性组中所有的属性值。
例如:(学号,课程名称)--> 分数
部分函数依赖:A-->B,如果A是一个属性组,则B属性值得确定只需要依赖于A属性组中某一些值即可。
例如:(学号,课程名称)-- > 姓名
传递函数依赖:A-->B,B -- >C . 如果通过A属性(属性组)的值,可以确定唯一B属性的值,在通过B属性(属性组)的值可以确定唯一C属性的值,则称 C 传递函数依赖于A
例如:学号-->系名,系名-->系主任
码:如果在一张表中,一个属性或属性组,被其他所有属性所完全依赖,则称这个属性(属性组)为该表的码
例如:该表中码为:(学号,课程名称)
* 主属性:码属性组中的所有属性
* 非主属性:除过码属性组的属性
第三范式(3NF):在2NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖)
四 数据库的备份与还原
1. 命令行:
语法:
备份 : mysqldump-u用户名 -p密码 数据库名 > 保存路径
还原 :
1. 登录数据库
2. 创建数据库
3. 使用数据库
4. 执行文件。source 文件路径
2. 图形化工具:
案例
SHOW DATABASES; -- 查询数据库
SHOW CREATE DATABASE db1;
SHOW TABLES; -- 查询表格
DESC stu; -- 查询表格结构
TRUNCATE TABLE stu;
CREATE TABLE stu (
id INT, -- 编号
NAME VARCHAR(20), -- 姓名
age INT, -- 年龄
sex VARCHAR(5), -- 性别
address VARCHAR(100), -- 地址
math INT, -- 数学
english INT -- 英语
);
INSERT INTO stu(id,NAME,age,sex,address,math,english)
VALUES
(1,'马云',55,'男', '杭州',66,78),
(2,'马化腾',45,'女','深圳',98,87),
(3,'马景涛',55,'男','香港',56,77),
(4,'柳岩',20,'女','湖南',76,65),
(5,'柳青',20,'男','湖南',86,NULL),
(6,'刘德华',57,'男','香港',99,99),
(7,'马德',22,'女','香港',99,99),
(8,'德玛西亚',18,'男','南京',56,65);
SHOW TABLES;
SELECT * FROM stu; -- 查询表格
TRUNCATE stu; -- 删除所有数据并创建一个一模一样的表格
SELECT
id 学号, -- 学号
NAME 姓名, -- 姓名
age 年龄, -- 年龄
sex 性别, -- 性别
address 地址, -- 地址
math 数学成绩, -- 数学成绩
english 英语成绩 -- 英语成绩
FROM stu;
-- 去除重复的结果集
SELECT DISTINCT address FROM stu; -- 查询地址
SELECT DISTINCT NAME,address FROM stu; -- 查询地址
-- 计算 math 和English 分数之和
SELECT NAME,math,english,math + english FROM stu;
-- 如果有null参与的运算, 计算结果都为null
SELECT NAME,math,english,math + IFNULL(english,0) FROMstu;
-- 起别名
SELECT NAME,math 数学,english 英语,math + IFNULL(english,0) 总分 FROM stu;
-- 查询年龄大于20岁的
SELECT * FROM stu WHERE age > 20;
-- 查询年龄等于20岁的
SELECT * FROM stu WHERE age = 20;
-- 查询年龄不等于20岁的
SELECT * FROM stu WHERE age != 20;
-- 查询年龄大于等于20岁 小于等于30的
SELECT * FROM stu WHERE age >=20 AND age <=30;
SELECT * FROM stu WHERE age BETWEEN 20 AND 30;
-- 查询年龄22岁, 18岁, 25岁的信息
SELECT * FROM stu WHERE age = 22 OR age = 18 OR age =25;
SELECT * FROM stu WHERE age IN(18,22,25);
SELECT * FROM stu WHERE age IN(18,22,25) AND sex = '女';
-- 查询英语成绩是null的
SELECT * FROM stu WHERE english = NULL; -- 不对的, null值不能使用=(!=) 去判断
SELECT * FROM stu WHERE english IS NULL;
-- 查询英语成绩不是null的
SELECT * FROM stu WHERE english IS NOT NULL;
-- 查询姓马的有哪些?
SELECT * FROM stu WHERE NAME LIKE '马%';
-- 查询第二个字是化的人
SELECT * FROM stu WHERE NAME LIKE "_化%";
-- 查询姓名是三个字的人
SELECT * FROM stu WHERE NAME LIKE '___';
-- 查询姓名中包含德的人
SELECT * FROM stu WHERE NAME LIKE '%德%';
SELECT * FROM stu; -- 查询表
-- 按照数学成绩升序排列(默认ASC 升序, DESC 降序)
SELECT * FROM stu ORDER BY math DESC;
-- 按照数学成绩升序排序, 如果成绩一样则按照英语成绩排名
SELECT * FROM stu ORDER BY math , english;
-- 查询个数
SELECT COUNT(IFNULL(english,0)) FROM stu;
SELECT COUNT(*) FROM stu; -- 不推荐
-- 查询数学成绩最大值/最小值 max /min
SELECT MAX(math) FROM stu;
-- 求和
SELECT SUM(math) FROM stu;
-- 求平均数
SELECT AVG(math) FROM stu;
-- 分组查询, 按照性别查询(男, 女分开)平均分, 分别的人数是多少
SELECT sex, AVG(math) FROM stu GROUP BY sex;
-- 分组查询, 按照性别查询(男, 女分开)平均分, 分别的人数是多少
SELECT sex, AVG(math), COUNT(id) FROM stu GROUP BYsex;
-- 分组查询, 按照性别查询(男, 女分开)平均分, 分别的人数,分数低于70分的人不参与分组
SELECT sex, AVG(math), COUNT(id) FROM stu WHERE math> 70 GROUP BY sex;
-- 分组查询, 按照性别查询(男, 女分开)平均分, 分别的人数,分数低于70分的人不参与分组, 分组之后人数要大于2个人
SELECT sex, AVG(math), COUNT(id) FROM stu WHERE math> 70 GROUP BY sex HAVING COUNT(id) > 2;
--
SELECT * FROM stu;
-- 每页显示3条记录
SELECT * FROM stu LIMIT 0,3; -- 第1页
SELECT * FROM stu LIMIT 3,3; -- 第2页
-- 公式 : 开始的索引 = (当前的页码 -1) * 每页显示的条数
CREATE TABLE IF NOT EXISTS tab_stu2(
id INT,
NAME VARCHAR(20) NOT NULL -- name 为非空
);
SELECT * FROM tab_stu2; -- 查询表格
INSERT INTO tab_stu2 VALUE(2,'张无忌');
INSERT INTO tab_stu2 VALUE(3, NULL);
DELETE FROM tab_stu2 WHERE id =3;
ALTER TABLE tab_stu2 MODIFY `name` VARCHAR(32) NOTNULL;
SELECT * FROM tab_stu3; -- 查询表格
CREATE TABLE tab_stu3(
id INT,
phone_number VARCHAR(20) UNIQUE-- 手机号
);
INSERT INTO tab_stu3 VALUE (1,'123');
INSERT INTO tab_stu3 VALUE (2,NULL);
SELECT * FROM tab_stu4;
-- 添加主键约束
CREATE TABLE tab_stu4(
id INT PRIMARY KEY,
NAME VARCHAR(32)
);
-- 删除主键
-- alter table tab_stu4 id int; -- 错误的
ALTER TABLE tab_stu4 DROP PRIMARY KEY;
-- 添加主键
ALTER TABLE tab_stu4 MODIFY id INT PRIMARY KEY;
CREATE TABLE tab_stu5(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(32)
);
SELECT * FROM tab_stu5;
-- 删除自动增长
ALTER TABLE tab_stu5 MODIFY id INT;
-- 添加自动增长
ALTER TABLE tab_stu5 MODIFY id INT AUTO_INCREMENT;

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马