先让我们回顾一下,上一章节的知识,看一个小练习:
提问:下面的语句有没有错误?实现了什么功能
SELECT * FROM `student`
WHERE `studentNo` IN (SELECT `studentNo` FROM result );
结果:没有错误 ; 查询学生表中,与成绩表里面学号相同的学生的信息
一。下面就进入本章的知识---高级查询
1. exists子查询
大家可以想一想,怎么样就可以去检测一张表有没有建立? 其实这的语法跟英语非常相似,用if判断一下
IF EXISTS student ;
CREATE TABLE student (..................) ;
我们可以做一些练习,来熟悉一下
#查询一下Logic Java 最后一次考试成绩大于80的记录
SELECT * FROM `result`
WHERE `subjectNo` = (
SELECT `subjectNo` FROM `subject` WHERE `subjectName` = 'Login Java'
) AND `examData` = (SELECT MAX(`examDate`) FROM `result`
WHERE `subjectNo` =(SELECT `subjectNo` FROM `subject` WHERE `subjectName` = 'Login Java')
) AND `studentResult`> 80 )
AND `subjectNo` = (SELECT `subjectNo` FROM `subject` WHERE `subjectName` = 'Login Java')
ORDER BY `studentResult` DESC #desc 是从高到低降序排序
LIMIT 5 ;
注:exists 和 in 是可以互换使用的,但in是逐个去查询,速度慢;而exists速度很快,它查询的结果只有两种:TRUE 或者FALSE,要么返回真,要么返回假 所以exists就分为了相关子查询、不相关子查询
我们做一个exists 和 in 的练习
#查询参加考试的学生信息,用in
SELECT * FROM student WHERE studentNo IN(
SELECT r. studentNo FROM result r )
#相关子查询,exists
SELECT * FROM student WHERE EXISTS(
SELECT r.studentNo FROM result r
WHERE r.studentNo = student.studentNo )
2.子查询的注意事项:
a)任何允许使用表达式的地方都可以用子查询
b)嵌套在父查询SELECT语句的子查询可以包括:
(1)SELECT语句
(2)FROM语句
(3)WHERE语句
(4)GROUP BY 语句
(5)HAVING 语句
c)只出现在子查询中而没有出现在父查询中的列,不可以包含在输出列中
3.下面做一些练习,巩固一下
(1)统计一下每个年级男女生人数
SELECT gradeID, sex ,COUNT(sex) FROM student
GROUP BY sex,gradeID
(2)查询每门课程的平均分,并且按照分数从大到小去排序
AVG(studentResult) FROM result
GROUP BY AVG(studentResult) DESC
我们可以总结一下语句的作用:
WHERE语句 : 用来筛选FROM子句中指定的操作所产生的行
GROUP BY 语句: 用来分组 WHERE子句的输出
HAVING语句 : 用来从分组的结果中筛选行
注意:如果先进行了分组排序GROUP BY,就不能在它后面使用WHERE语句;这个时候如果还想继续添加条件,只能使用HAVING 语句!!!
二。常用的多表连接查询
1.内连接(INNER JOIN)和外连接---左外连接(LEFT JOIN)跟右外连接(RIGHT JOIN)
#查询学生的学号、学生姓名、学生成绩
SELECT studentNo,studentName,studentResult FROM student
INNER JOIN result ON
也可以用第二种方法写:
SELECT studentNo,studentName,studentResult FROM student,result
WHERE ...............................
注意: 使用INNER JOIN 内连,连接的两张表,两者必须要有共同匹配的内容!!!
LEFT JOIN 左侧的为主表 ;RIGHT JOIN 右侧的为 主表
三。如何去创建表?需要满足什么条件?
三大范式:
a)第一范式:确保每列的原子性.
如果每列(或者每个属性)都是不可再分的最小数据单元(也称为最小的原子单元),则满足第一范式.
例如:顾客表(姓名、编号、地址、……)其中"地址"列还可以细分为国家、省、市、区等。
b)第二范式:在第一范式的基础上更进一层,目标是确保表中的每列都和主键相关.
如果一个关系满足第一范式,并且除了主键以外的其它列,都依赖于该主键,则满足第二范式.
例如:订单表(订单编号、产品编号、定购日期、价格、……),"订单编号"为主键,"产品编号"和主键列没有直接的关系,即"产品编号"列不依赖于主键列,应删除该列。
c)第三范式:在第二范式的基础上更进一层,目标是确保每列都和主键列直接相关,而不是间接相关.
!!如果一个关系满足第二范式,并且除了主键以外的其它列都不依赖于主键列,则满足第三范式.
为了理解第三范式,需要根据Armstrong公里之一定义传递依赖。假设A、B和C是关系R的三个属性,如果A-〉B且B-〉C,则从这些函数依赖中,可以得出A-〉C,如上所述,依赖A-〉C是传递依赖。
例如:订单表(订单编号,定购日期,顾客编号,顾客姓名,……),初看该表没有问题,满足第二范式,每列都和主键列"订单编号"相关,再细看你会发现"顾客姓名"和"顾客编号"相关,"顾客编号"和"订单编号"又相关,最后经过传递依赖,"顾客姓名"也和"订单编号"相关。为了满足第三范式,应去掉"顾客姓名"列,放入客户表中。
四。事务
1.首先我们了解一下它的定义:事务是作为单个逻辑工作单元执行的一系列操作
多个操作作为一个整体向系统提交,要么都执行,要么都不执行
事务是一个不可分割的工作逻辑单元
2.事务必备的4个属性,简称ACID属性 :
原子性(Atomiccity): 事务是一个完整的操作,每一步都是不可以分的
一致性(Consistency): 当事务完成时,数据必须处于同一状态
隔离性(Isolation): 并发事务之间彼此隔离、独立,它不应该以任何方式依赖或影响了其他事务
持久性(Durability): 事务完成后,它对数据库的修改是会被永久保持的
3.我们可以去思考一下,怎么样就能够创建一个事务?(拓:MySQL中支持事务的引擎有 InnoDB 和 BDB)
先列一下语法:
开始事务用 ---- BEGIN 或者 START TRANSACTION
提交事务 ---- COMMIT
回滚事务 ---- ROLLBACK
做一个练习,来感受一下它的用法:
#转账---张三给李四转500元,求转账之后两人户头的金额
CREATE DATABASE mybank;
USE mybank;
CREATE TABLE `bank`(
`customerName` CHAR(10), #用户名
`currentMoney` DECIMAL(10,2) #当前余额
);
INSERT INTO `bank`(`customerName`,`currentMoney`)
VALUES('张三',1000);
INSERT INTO `bank`(`customerName`,`currentMoney`) VALUES('李四',1);
BEGIN;
UPDATE `bank` SET `currentmoney` = `currentmoney` - 500
WHERE `customerName` = ' 张三' ;
UPDATE `bank` SET `currentmoney` = `currentmoney` +500
WHERE `customerName` = '李四' ;