13、JavaWeb进阶——MySQL加强

1、数据库三范式

  • 第一范式:对关系模型的基本要求,如果不满足第一范式的数据库就不是关系型数据库,是指数据库的每一张数据库表都是不可分割的基本数据项,同一列中不能有多个值。
    • 解释
      在这里插入图片描述
    • 重新设计使其满足第一范式
      在这里插入图片描述
  • 第二范式:要求表中的每一行都能够被唯一区分。(主键)
    • 遵循第二范式,如果查询时基于主键查询的,查询的性能就会高,(因为主键会自动建立索引)
    • 并不是所有的表都会有根据主键查询的需求,例如上图中的user_hobby表,所以并不是所有表都要遵循第二范式。
  • 第三范式:一个表不能包含其他表的其他非主键信息。
    • 解释
      在这里插入图片描述
      在这里插入图片描述
    • 使用规范
      • 部门名称经常修改的时候,必须遵守第三范式,否则如果部门名称发生改变,员工表也要进行一次修改
      • 部门不经常修改的时候,就不需要遵守第三范式,具体要求看实际需求。

2、SQL分类(了解)

1、数据查询语句(DQL)

用以从表中获得数据,确定数据怎样在应用程序给出。保留字 SELECT 是 DQL(也是所有 SQL)用得最多的动词,其他 DQL 常用的保留字有 WHERE,ORDER BY,GROUP BY 和 HAVING。这些 DQL 保留字常与其他类型的 SQL 语句一起使用。

2、数据定义语言(DDL)

其语句包括动词 CREATE 和 DROP。在数据库中创建新表或删除表(CREAT TABLE 或 DROP TABLE);为表加入索引等。DDL 包括许多与人数据库目录中获得数据有关的保留字。它也是动作查询的一部分。

3、数据操作语言(DML)

其语句包括动词 INSERT,UPDATE 和 DELETE。它们分别用于添加,修改和删除表中的行,Insert / Update / Delete。也称为动作查询语言。

4、事务处理语言(TCL)

它的语句能确保被 DML 语句影响的表的所有行及时得以更新。TCL 语句包括 BEGIN TRANSACTION,COMMIT 和 ROLLBACK。

5、数据库控制语言(DCL)

它的语句通过 GRANT 或 REVOKE 获得许可,确定单个用户和用户组对数据库对象的访问。某些 RDBMS 可用 GRANT 或 REVOKE 控制对表单个列的访问。

6、指针控制语言(CCL)

它的语句,像 DECLARE CURSOR,FETCH INTO 和 UPDATE WHERE CURRENT 用于对一个或多个表单独行的操作。

3、单表查询(熟练掌握)

1、语法

SELECT [DISTINCT] * | 字段 [别名] [, 字段 [别名]]
FROM 表名称 [别名]
[WHERE 条件(S)]
[ORDER BY 字段 [ASC|DESC] [, 字段 [ASC|DESC],]];

2、全列和投影查询

  • 查询所有员工信息
SELECT * FROM employee;
  • 查询每个员工的编号、姓名、职位
SELECT EMPNO,ENAME,JOB FROM employee;
  • 查询所有部门信息
SELECT * FROM dept;

3、消除重复

  • 查询所有有员工的部门编号
SELECT DISTINCT DEPTNO FROM emp; 
  • 查询有员工的部门和职位
SELECT DISTINCT DEPTNO,JOB FROM emp; 

4、算数运算符

  • 查询所有员工的年薪
SELECT *,(sal+IFNULL(comm,0))*12 FROM emp 
  • 查询所有员工的年薪(使用别名)
SELECT *,(sal+IFNULL(comm,0))*12 AS 年薪 FROM emp 

5、过滤查询

1、注意事项

  • 字符串和日期要使用单引号括起来
  • 数字类型直接书写
  • 字符串是大小写不敏感的,日期格式化大小写敏感的;

2、空值

  • 空值是指不可用、未分配的值、也就是没有值
  • 空值不等于0或空格,也不表示空字符串
  • 任意类型都支持空值。
  • 包括空值的任意运算表达式的结果都是空值
  • 使用函数IFNULL(expr1,expre2),如果expr1不是null,返回expr1,否则返回expr2

3、常用算术比较运算符

  • =,!=,<>,>,>=,<,<=

  • BETWEEN … AND …:在两值之间 (包含开始和结尾,数学中的闭区间)

  • IN:匹配列出的值;如:IN(1, 2, 3, 4)

  • LIKE :匹配字符串模式, _ 、%,LIKE 运算符必须使用通配符才有意义;

    • 匹配单个字符:_ 表示 1 个;
      • 匹配任意多个字符:% 表示 0个、1个、多个。
  • IS NULL:是否为空

  • 查询所有员工的年薪((月薪 + 奖金) * 12)

SELECT *,(SAL+IFNULL(COMM,0)) FROM emp 
  • 查询有奖金的员工信息
SELECT * FROM emp  WHERE COMM IS NOT NULL
  • 查询公司的老板
SELECT * FROM emp WHERE MGR IS NULL
  • 查询出基本工资高于 1500 的所有员工信息
SELECT * FROM emp WHERE SAL>1500
  • 查询名字叫 SCOTT 的员工所从事的工作
SELECT JOB FROM emp WHERE ENAME ='SCOTT'
  • 查询 1981 年入职的员工信息
SELECT * FROM emp WHERE HIREDATE BETWEEN'1981-1-1' AND  '1981-12-31'
  • 查询年薪小于 3W 的员工
SELECT *,(SAL+IFNULL(COMM,0)) AS yearSal FROM emp WHERE (SAL+IFNULL(COMM,0))<30000
  • 查询所有不是销售人员的员工信息
SELECT * FROM emp WHERE JOB!= 'SALESMAN'
  • 查询工资在 2000-3000 之间的员工信息
SELECT * FROM emp WHERE SAL BETWEEN 2000 AND 3000
  • 查询工资为 800 或 1600 或 3000 的员工
SELECT * FROM emp WHERE SAL IN (800,1600,3000)
  • 查询出所有雇员姓名是以 A 开头的全部雇员信息。
SELECT * FROM emp WHERE ENAME LIKE 'A%'
  • 查询出雇员姓名第二个字母是 M 的全部雇员信息。
SELECT * FROM emp WHERE ENAME LIKE '_M%'
  • 查询出雇员姓名任意位置上包含字母 A 的全部雇员信息。
SELECT * FROM emp WHERE ENAME LIKE '%A%'

4、逻辑运算符

  • AND:如果组合的条件都是 true,返回 true;

  • OR:如果组合的条件 之一是 true ,返回 true;

  • NOT:如果下面的条件是 false,返回 true。

  • 优先级规则:比较运算符 > NOT > AND > OR

  • 查询姓名中有 e 或者 a 的员工姓名

SELECT * FROM emp WHERE ENAME LIKE '%e%' OR '%a%'
  • 查询工资在 1500~3000 之间的全部员工信息
SELECT * FROM emp WHERE SAL>=1500 AND SAL<=3000
  • 查询工资不在 2000-3000 之间的员工信息
SELECT * FROM emp WHERE SAL<2000 OR SAL>3000
  • 查询工资不为 800 或 1600 或 3000 的员工
SELECT * FROM emp WHERE SAL NOT IN (800,1600,3000)
  • 查询出职位是办事员 (CLERK) 或者是销售人员 (SALESMAN) 的全部信息,且工资在 1000 以上
SELECT * FROM emp WHERE (JOB='CLERK' OR JOB='SALESMAN') AND SAL > 1000

5、结果排序

  • ASC:升序,缺省

  • DESC:降序

  • ORDER BY 子句出现在 SELECT 语句后执行;

  • ORDER BY 可以使用别名,但不能使用加了引号的别名或列名来排序,没有效果

  • 查询所有员工信息,按照工资排序

SELECT * FROM emp ORDER BY SAL DESC
  • 查询所有员工信息,按照年薪降序排序
SELECT *,(SAL+IFNULL(COMM,0)) AS yearSal FROM emp ORDER BY yearSal DESC
  • 查询所有员工信息,按照部门和年薪降序排序
SELECT *,(SAL+IFNULL(COMM,0)) AS yearSal FROM emp ORDER BY yearSal ASC, DEPTNO ASC

4、多表查询(熟练掌握)

1、笛卡尔积

【数学定义】: 假设集合 A = {a, b},集合 B = {0, 1, 2},则两个集合的笛卡尔积为 {(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}。

【MySQL 定义】: 多表查询会产生笛卡尔积,比如:SELECT * FROM emp, dept,实际运行环境下,应避免使用全笛卡尔集。

2、多表查询分类

  • 内连接查询
    • 隐式内连接查询
    • 显示内连接查询
  • 外连接查询
    • 左外连接查询
    • 右外连接查询
    • 全外连接查询

3、内连接查询

1、隐式内连接查询

【语法】:

SELECT [DISTINCT] * | 字段 [别名] [, 字段 [别名],]
FROM 表名称 [别名], [表名称 [别名],]
[WHERE 条件(S)/消除笛卡尔积连接]
[ORDER BY 排序字段 [ASC|DESC] [, 排序字段 [ASC|DESC],]];

【注意事项】:

  • 在where子句中写入连接条件

  • 当多个表中有重列名的时候,必须在列的名字前面加上表名作为前缀或者使用表的别名

  • 等值连接时连接操作通常是在存在主外键约束条件的多表上建立的,连接条件中的两个字段通过等号建立等值关系。

  • 查询员工编号,员工名称,员工所属部门的编号和名称

SELECT * FROM emp AS e,dept AS d WHERE e.DEPTNO=D.DEPTNO
  • 查询员工的姓名,工资,所在部门的名称,以及工资的等级
SELECT ENAME,SAL,GRADE FROM emp AS e,dept AS d,salgrade AS s WHERE e.DEPTNO=d.DEPTNO AND e.SAL BETWEEN s.LOSAL AND s.HISAL

2、显示内连接查询

【语法】:

SELECT table1.column, table2.column
FROM table1 [INNER] JOIN table2 ON table1.column1 = table2.column2
WHERE 条件

【举例】:

  • 查询员工编号,员工名称,员工所属部门的编号和名称
SELECT * FROM emp AS e
JOIN dept AS d ON e.DEPTNO=D.DEPTNO
  • 查询员工的姓名,工资,所在部门的名称,以及工资的等级
SELECT ENAME,SAL,GRADE FROM emp AS e 
JOIN dept AS d ON  e.DEPTNO=d.DEPTNO 
JOIN salgrade AS s  ON e.SAL BETWEEN s.LOSAL AND s.HISAL

4、外连接查询

【需求】:

  • 查询出员工的编号,名字,薪水和所在部门的名称
SELECT emp.EMPNO, emp.ENAME, emp.SAL, dept.DNAME FROM emp JOIN dept ON emp.DEPTNO = dept.DEPTNO

【问题】:
没有部门的员工则查询不出来

1、左外连接查询

SELECT emp.EMPNO, emp.ENAME, emp.SAL, dept.DNAME FROM emp LEFT JOIN dept ON emp.DEPTNO = dept.DEPTNO

【特点】:

  • 查询出JOIN左边表的全部数据,右边表中不匹配的数据使用NULL填充

2、右外连接查询

SELECT emp.EMPNO, emp.ENAME, emp.SAL, dept.DNAME FROM emp RIGHT JOIN dept ON emp.DEPTNO = dept.DEPTNO

【特点】:

  • 查询出JOIN右边表的全部数据,左边不匹配的数据使用NULL填充

5、分组函数(熟练掌握)

1、函数分类

  • 单行函数:将每条数据进行独立的计算,然后每一条数据得到一条结果。
  • 多行函数:多条数据同时计算,最终得到一条结果数据。也称为聚集函数、分组函数、主要用来完成一些统计的功能。

2、多行函数

  • COUNT():查询表中的数据记录;
  • AVG():求出平均值;
  • SUM():求和;
  • MAX():求出最大值;
  • MIN():求出最小值。

【使用注意事项】:

  • 统计函数忽略空值,可以使用IFNULL,因为NULL不会影响汇总值,但是会影响汇总总数量。
  • 不可以在WHERE中使用分组函数。
  • 在汇总总数的时候,出现在COUNT中的列不能包含空值,一般推荐使用主键或者*

【举例】:

  • 查询所有员工每个月的平均工资及总工资
SELECT SUM(SAL), SUM(SAL)/COUNT(*) FROM emp
  • 查询月薪在 2000 以上的员工总人数
SELECT COUNT(*) FROM emp WHERE SAL>2000
  • 查询员工最高工资和最低工资差距
SELECT MAX(SAL)-MIN(SAL) FROM emp

6、分组查询

1、语法

SELECT [DISTINCT] *|分组字段1 [别名] [, 分组字段2 [别名] ,] | 统计函数
FROM 表名称 [别名], [表名称 [别名] ,]
[WHERE 条件(s)]
[GROUP BY 分组字段1 [, 分组字段2 ,]]
[ORDER BY 排序字段 ASC | DESC [, 排序字段 ASC | DESC]];

【举例】:

  • 按照职位分组,求出每个职位的最高和最低工资
SELECT JOB,MIN(SAL),MAX(SAL) FROM emp GROUP BY JOB
  • 查询出每一个部门员工的平均奖金
SELECT *,SUM(COMM)/COUNT(*) FROM emp GROUP BY DEPTNO

2、使用注意事项

  • SELECT 子句出现的字段,要不在统计函数中,要不出现在 GROUP BY 子句中,否则不合理(整体与个体);
  • 在GROUP BY 子句中出现的字段,可以不出现在 SELECT 列表中;
  • 统计函数可以单独使用,SQL 中可以没有 GROUP BY 子句;
  • 在 GROUP BY 子句中,可以按单列进行分组,也可以在多列上进行分组,多列分组就是按照多个字段的组合进行分组,最终的结果也会按照分组字段进行排序显示。

【举例】:

  • 查询出每一个部门员工的平均工资
SELECT *,AVG(SAL) FROM emp GROUP BY DEPTNO
  • 查询各个部门和岗位的平均工资
SELECT *,AVG(SAL) FROM emp GROUP BY DEPTNO,JOB

3、分组限定

  • 不能在 WHERE 子句中对分组限定,限制组须使用 HAVING 子句(分组之后过滤需要使用 HAVING 子句);
  • 不能在 WHERE 子句中使用统计函数,而在 HAVING 子句可使用统计函数。

【举例】:

  • 查询部门平均工资高于 2000 的部门及其平均工资
SELECT *, AVG(SAL) FROM emp GROUP BY DEPTNO HAVING AVG(SAL)>2000
  • 查询在 80, 81, 82 年各进公司多少人
SELECT COUNT(*) ,YEAR(HIREDATE) AS y FROM emp GROUP BY YEAR(HIREDATE) HAVING y BETWEEN '1980' AND '1982'
  • 查询各个管理人员下员工的平均工资,其中最低工资不能低于 1300,不计算老板
SELECT AVG(SAL), MGR,MIN(SAL) AS minsal FROM emp GROUP BY MGR HAVING MGR IS NOT NULL AND minsal>=1300

7、单行函数(了解)

1、日期函数

  • NOW():获取当前时间;
  • DAY(date):获取日期中的天数,范围是从 1 到 31;
  • HOUR(time):返回 time 对应的小时数,范围是从 0 到 23;
  • MINUTE(time):返回 time 对应的分钟数,范围是从 0 到 59;
  • MONTH(date):返回 date 对应的月份,范围时从 1 到 12;
  • YEAR(date):返回 date 对应的年份,范围是从 1000 到 9999;
  • LAST_DAY(date):获取一个日期或日期时间值,返回该月最后一天对应的值。

8、子查询(掌握)

1、定义和作用

【定义】: 子查询指的就是在一个查询之中嵌套了其他若干查询。

【作用】: 在使用查询的时候,会出现限制条件不是确定的值,而是来源于一个查询结果。

【语法】:

SELECT select_list
FROM	table
WHERE	expr operator (SELECt select_list FROM table)

【使用注意事项】:

  • 子查询一般出现在form和where子句中
  • 子查询要使用圆括号括起来
  • 将子查询放在比较运算符的右边
  • 子查询在主查询执行之前先执行一次,主查询使用子查询的结果,但不宜嵌套过多。

2、分类

  • 单行单列:只包含一个字段的查询,返回的查询结果也只包含一行数据。
  • 多行单列:只包含一个字段的查询,返回的查询结果可能是多行或者零行。
  • 多行多列:包含多个字段的返回,查询结果可能是单行或者多行。

【举例】:

  • 查询出工资比 MARTIN 还要高的全部雇员信息
SELECT * FROM emp WHERE sal > (SELECT sal FROM emp WHERE ename = 'MARTIN')
  • 查询平均工资高于公司平均工资的部门信息
SELECT e.deptno, d.dname, AVG(sal) 
FROM emp e JOIN dept d  ON e.deptno = d.deptno 
GROUP BY deptno HAVING AVG(sal) >= (SELECT AVG(sal) FROM emp)
  • 查询出每个部门的编号、名称、部门人数、平均工资
SELECT  dept.deptno, temp.count, temp.avg  
FROM dept JOIN (SELECT deptno dno, COUNT(empno) count, AVG(sal) avg  FROM emp GROUP BY deptno) temp ON dept.deptno = temp.dno
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

执手天涯@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值