1.创建数据库表
【1】创建数据库表t_student
(1)创建数据库:
(2)新建查询
(3)创建数据库表
##单行注释 /* 多行注释 多行注释 */ /* 建立一张用来存储学生信息的表 字段包含学号、姓名、性别、年龄、入学日期、班级、email等信息 */ ##创建数据库表: CREATE TABLE t_student( sno int(6),-- 6显示长度 sname VARCHAR(10), sex char(1), age int(3), enterdate date, classname VARCHAR(10), email VARCHAR(15) ); -- 查看表的结构:展示表的字段的详细信息 desc t_student; -- 查看表中数据: SELECT * FROM t_student; -- 查看建表语句: SHOW CREATE TABLE t_student;
1.1数据库表列类型
2.对数据的增删改查操作
2.1查询、添加数据
-- 查看表中记录: SELECT * FROM t_student; -- 在t_student数据库表中插入数据: INSERT INTO t_student VALUES(1,'zhangsan','男',18,'2022.5.8','软件1班','123@163.com'); INSERT INTO t_student VALUES(100100100,'zhangsan','男',18,'2022.5.8','软件1班','123@163.com'); INSERT INTO t_student VALUES(100100100,"zhangsan","男",18,"2022.5.8","软件2班","123@163.com"); INSERT INTO t_student VALUES(7,"zhangsan","男",18,NOW(),"软件2班","123@163.com"); -- 如果不是全字段插入数据的话,需要加入字段的名字。 INSERT INTO t_student (sno,sname,sex)VALUES(7,"zhangsan","男");
插入数据的注意事项:
2.2修改、删除数据
-- 查看表中记录: SELECT * FROM t_student; -- 在t_student数据库表中插入数据: INSERT INTO t_student VALUES(1,'zhangsan','男',18,'2022.5.8','软件1班','123@163.com'); INSERT INTO t_student VALUES(100100100,'zhangsan','男',18,'2022.5.8','软件1班','123@163.com'); INSERT INTO t_student VALUES(100100100,"zhangsan","男",18,"2022.5.8","软件2班","123@163.com"); INSERT INTO t_student VALUES(7,"zhangsan","男",18,NOW(),"软件2班","123@163.com"); -- 如果不是全字段插入数据的话,需要加入字段的名字。 INSERT INTO t_student (sno,sname,sex)VALUES(7,"zhangsan","男"); -- 修改表中的数据 UPDATE t_student SET sex = '女'; UPDATE t_student SET sex = '男' WHERE sno = 7; UPDATE t_student SET classname = 'java01' WHERE sno = 100100100; UPDATE t_student SET classname = 'JAVA01' WHERE sno = 1; UPDATE t_student SET age = 29 WHERE classname = 'java01'; -- 删除表中的数据 DELETE FROM t_student WHERE sno = 1;
2.3修改、删除数据库表
-- 查看数据 SELECT * FROM t_student; -- 修改表的结构 -- 增加一列 ALTER TABLE t_student ADD score DOUBLE(5,2);-- 5是总位数 2是小数位数 UPDATE t_student SET score = 90.589 WHERE sno = 7; -- 增加一列 放在最前面 ALTER TABLE t_student ADD score DOUBLE(5,2) FIRST;-- 5是总位数 2是小数位数 -- 增加一列 放在sex列的后面 ALTER TABLE t_student ADD score DOUBLE(5,2) AFTER sex;-- 5是总位数 2是小数位数 ALTER TABLE t_student DROP score;-- 删除一列 -- 修改一列 ALTER TABLE t_student MODIFY score FLOAT(4,1);-- modify修改的是列的类型的定义,但是不会改变列的名字 ALTER TABLE t_student CHANGE score score1 DOUBLE(3,1);-- change 修改的是列名和列的类型定义 -- 删除表 DROP TABLE t_student;
3.表的完整性约束
3.1非外键约束
/* 建立一张用来存储学生信息的表 字段包含学号、姓名、性别,年龄、入学日期、班级,emai1等信息 约束: 建立一张用来存储学生信息的表字段包含学号、姓名、性别,年龄、入学日期、班级,emai1等信息 【1】学号是主键 不能为空 + 唯一 ,主键的作用:可以通过主键查到唯一的一条记录 【2】如果主键是整数类型,那么需要自增 【3】姓名不能为空 【4】Email唯一 【5】性别默认值是男 【6】性别只能是男女 【7】年龄只能在18-50之间 */ CREATE TABLE t_student( sno int(6) PRIMARY key auto_increment, sname VARCHAR(10) NOT NULL, sex char(1) DEFAULT'男' CHECK(sex='男'||sex = '女'), age int(3) CHECK(age>=18&&age<=40), enterdate date, classname VARCHAR(10), email VARCHAR(15) UNIQUE );
【1】约束从作用上可以分为两类:
(1)表级约束:可以约束表中任意一个或多个字段。与列定义相互独立,不包含在列定义中;与定义用','分隔;必须指出要约束列的名称。
(2)列级约束:包含在列定义中,直接跟在该列的其他定义之后,用空格分隔,不必指定列名
-- 删除表 DROP TABLE t_student; CREATE TABLE t_student( sno int(6) auto_increment, -- auto_increment 只能是列级约束 sname VARCHAR(10) not null, -- not null 只能是列级约束 sex char(1) DEFAULT '男' ,-- DEFAULT 只能是列级约束 age int(3), enterdate date, classname VARCHAR(10), email VARCHAR(15), CONSTRAINT pk_stu PRIMARY KEY(sno), -- pk_stu 主键约束的名字 CONSTRAINT ck_stu_sex CHECK(sex='男'||sex='女'), CONSTRAINT ck_stu_age CHECK(age>=20&&age<=40), CONSTRAINT uq_stu_email UNIQUE(email) ); -- 添加数据
【2】在创建表以后添加约束(注意,要想一起添加 要在每个句子后面添加分号)
查看表的结构的语句: desc t_student;
3.2外键约束
主表(父表):班级表 - 班级编号 - 主键
从表(子表):学生表 - 编辑编号 - 外键
【2】sql演示:
-- 先创建父表:班级表: CREATE TABLE t_class( cno int(4) PRIMARY KEY auto_increment, cname VARCHAR(10) not null, croom CHAR(8) ); -- 添加班级数据 INSERT into t_class value(null,'java001','803教室') INSERT into t_class value(null,'java002','416教室') INSERT into t_class value(null,'大数据001','103教室') -- 可以一次性添加多条记录: INSERT into t_class value(null,'java001','803教室'),(null,'java002','416教室'),(null,'大数据001','103教室'); -- 查询一下班级表 select * FROM t_class; -- 创建子表 DROP TABLE t_student; CREATE TABLE t_student( sno int(6) PRIMARY key auto_increment, sname VARCHAR(10) NOT NULL, classname VARCHAR(10), email VARCHAR(15) UNIQUE, classno VARCHAR(10) -- 取值参考t_class表中的cno字段,不要求字段名字完全一致,但是长度定义 尽量保证相同。 ); INSERT into t_student (sno,sname,classname)values (null,'张三',1),(null,'李四',1),(null,'王五',3); -- 查看学生表 SELECT * FROM t_student; -- 出现问题: -- 1.我想添加一个学生对应的班级编码为4 INSERT into t_student (sno,sname,classname)values (null,'丽丽',4); -- 2.想删除班级2 DELETE FROM t_class where cno= 2; -- 出现问题的原因:因为你的外键约束,没用语法添加进去,现在只是在逻辑上认为班级编号是外键,没有在语法上定义 -- 解决办法:添加外键约束 -- 注意:外键约束只有表级约束,没有列级约束 CREATE TABLE t_student( sno int(6) PRIMARY key auto_increment, sname VARCHAR(10) NOT NULL, classname int(4), -- 取值参考t_class表中的cno字段,不要求字段名字完全一致,但是长度定义 尽量保证相同。 email VARCHAR(15) UNIQUE, classno VARCHAR(10), CONSTRAINT fk_stu_classno FOREIGN KEY (classname) REFERENCES t_class(cno) ); CREATE TABLE t_student( sno int(6) PRIMARY key auto_increment, sname VARCHAR(10) NOT NULL, classname VARCHAR(10), email VARCHAR(15) UNIQUE, classno VARCHAR(10),-- 取值参考t_class表中的cno字段,不要求字段名字完全一致,但是长度定义 尽量保证相同。 ); -- 在创建表以后添加外键约束: ALTER TABLE t_student add CONSTRAINT fk_stu_classno FOREIGN KEY (classname) REFERENCES t_class(cno);
【3】外键策略
-- 先创建父表:班级表: CREATE TABLE t_class( cno int(4) PRIMARY KEY auto_increment, cname VARCHAR(10) not null, croom CHAR(8) ); -- 添加班级数据 INSERT into t_class value(null,'java001','803教室'),(null,'java002','416教室'),(null,'大数据001','103教室'); -- 创建子表 CREATE TABLE t_student( sno int(6) PRIMARY key auto_increment, sname VARCHAR(10) NOT NULL, classname int(4), -- 取值参考t_class表中的cno字段,不要求字段名字完全一致,但是长度定义 尽量保证相同。 CONSTRAINT fk_stu_classno FOREIGN KEY (classname) REFERENCES t_class(cno) ); INSERT into t_student (sno,sname,classname)values (null,'张三',1),(null,'李四',1),(null,'王五',3); -- 查看学生表 SELECT * FROM t_student; -- 查询一下班级表 select * FROM t_class; -- 删除班级1:如果直接删除的话肯定不行因为有外键约束: -- 为了解决这个问题加入外键策略: -- 策略1: no action 不允许操作 -- 通过操作sql来完成: 先把班级2的学生对应的班级 改为null UPDATE t_student SET CLASSNAME = NULL WHERE CLASSNAME = 1; DELETE FROM t_class where cno = 1; -- 策略2:cascade 级联操作:操作主表的时候影响从表的外键信息: -- 先删除之前的外键约束: alter TABLE t_student DROP FOREIGN KEY fk_stu_classno; -- 重新添加外键 alter TABLE t_student add CONSTRAINT fk_stu_classno FOREIGN KEY (classname) REFERENCES t_class(cno) on UPDATE CASCADE ON DELETE CASCADE; -- 策略3:set null 置空操作: -- 先删除之前的外键约束: alter TABLE t_student DROP FOREIGN KEY fk_stu_classno; -- 重新添加外键 alter TABLE t_student add CONSTRAINT fk_stu_classno FOREIGN KEY (classname) REFERENCES t_class(cno) on UPDATE set NULL ON DELETE set NULL; -- 注意: -- 1.策略2 级联操作 和策略3 的删除操作可以混着使用: alter TABLE t_student add CONSTRAINT fk_stu_classno FOREIGN KEY (classname) REFERENCES t_class(cno) on UPDATE CASCADE ON DELETE set NULL; -- 2.应用场合: -- (1)朋友圈删除,点赞和评论都删除 级联操作 -- (2)解散班级,对应的就是置空操作
3.3对DDL和DML的补充
【1】sql展示:
-- 创建表 CREATE TABLE t_student( sno int(6) PRIMARY key auto_increment, sname VARCHAR(10) NOT NULL, sex char(1) DEFAULT'男' CHECK(sex='男'||sex = '女'), age int(3) CHECK(age>=18&&age<=40), enterdate date, classname VARCHAR(10), email VARCHAR(15) UNIQUE ); -- 添加数据 INSERT INTO t_student VALUES (null,'王','男',18,'2020.1.2','java01班','123@789'); INSERT INTO t_student VALUES (null,'雪','男',19,'2020.1.2','java01班','12@789'); INSERT INTO t_student VALUES (null,'健','男',20,'2020.1.2','java01班','1@789'); -- 查看学生表 SELECT * FROM t_student; -- 添加一个表:快速添加:结构和数据跟t_student都是一致的 CREATE TABLE t_student2 AS SELECT * FROM t_student; -- 查看学生表2 SELECT * FROM t_student2; -- 快速添加:结构跟student一致,数据没有 CREATE TABLE t_student3 AS SELECT * FROM t_student WHERE 1 = 2; -- 查看学生表3 SELECT * FROM t_student3; -- 快速添加:只要部分列,部分数据: CREATE TABLE t_student4 AS SELECT sno,sname,age FROM t_student WHERE sno =2; -- 查看学生表4 SELECT * FROM t_student4;. -- 删除数据操作:只是清空数据 DELETE FROM t_student; TRUNCATE TABLE t_student;
【2】delete和truncate的区别:
4.DQL-查询操作
4.1表的准备
准备四张表:dept(部门表),emp(员工表),salgrade(薪资等级表),bonus(奖金表)
-- 创建部门表:属性有部门号,部门名字,LOC CREATE table DEPT( deptno int(2) not null, deptname VARCHAR(14), loc VARCHAR(13) ) -- 给部门表加了一个主键 ALTER TABLE dept add CONSTRAINT PK_DEPT PRIMARY KEY (deptno); -- 创建一个EMP员工表 CREATE table EMP( empno int(4) PRIMARY KEY, empname VARCHAR(10), job VARCHAR(9), mgr int(4), hiredate DATE, sal DOUBLE(7,2), comm DOUBLE(7,2), deptno int(2) ) -- 给员工表加一个外键,关联的是DEPT表中的deptno ALTER TABLE emp add CONSTRAINT FK_deptno FOREIGN KEY (deptno) REFERENCES DEPT (deptno) -- 创建薪资等级表SALGRADE CREATE TABLE SALGRADE( grade int PRIMARY KEY, losal DOUBLE(7,2), hisal DOUBLE(7,2) ) -- 创建奖金表 CREATE TABLE BONUS( ename VARCHAR(10), job VARCHAR(9), sal DOUBLE(7,2), comm DOUBLE(7,2) ) INSERT INTO DEPT(deptno,deptname,loc) VALUES(10,'ACCOUNTING','NEW YORK'); INSERT INTO DEPT(deptno,deptname,loc) VALUES(20,'RESEARCH','DALLAS'); INSERT INTO DEPT(deptno,deptname,loc) VALUES(30,'SALES','CHIGAGO'); INSERT INTO DEPT(deptno,deptname,loc) VALUES(40,'OPERATIONS','BOSTON'); INSERT INTO EMP(empno,empname,job,mgr,hiredate,sal,comm,deptno) VALUES(7369,'SMITH','CLERK',7902,'1980-12-17',800,null,20); INSERT INTO EMP(empno,empname,job,mgr,hiredate,sal,comm,deptno) VALUES(7499,'ALLEN','SALESMAN',7698,'1981-02-20',1600,300,30); INSERT INTO EMP(empno,empname,job,mgr,hiredate,sal,comm,deptno) VALUES(7521,'WARD','SALESMAN',7698,'1981-02-22',1250,500,30); INSERT INTO EMP(empno,empname,job,mgr,hiredate,sal,comm,deptno) VALUES(7566,'JONES','MANAGER',7839,'1981-04-02',2975,null,20); INSERT INTO EMP(empno,empname,job,mgr,hiredate,sal,comm,deptno) VALUES(7654,'MARTIN','SALESMAN',7698,'1981-09-28',1250,1400,30); INSERT INTO EMP(empno,empname,job,mgr,hiredate,sal,comm,deptno) VALUES(7698,'BLAKE','MANAGER',7839,'1981-05-01',2850,null,30); INSERT INTO EMP(empno,empname,job,mgr,hiredate,sal,comm,deptno) VALUES(7782,'CLARK','MANAGER',7839,'1981-06-09',2450,null,10); INSERT INTO SALGRADE(grade,losal,hisal) VALUES(1,700,1200),(2,1201,1400),(3,1401,2000),(4,2001,3000),(5,3001,9999); -- 查看表 -- 部门表:dept:department 部门,loc - location 位置 SELECT * FROM DEPT; -- 员工表:emp:employee 员工 ,mgr:manager 上级领导编号,hiredate:入职日期, common:补助, -- deptno 外键 参考的是 dept里面的deptno字段 -- mgr 外键 参考的是 自身表emp里面的empno产生了自关联的效果 SELECT * FROM emp; SELECT * FROM salgrade; SELECT * FROM bonus;
4.2单表查询
4.2.1最简单的SQL查询
-- 对emp表查询: SELECT * FROM emp; -- *代表所有数据 -- 显示部分列: SELECT empno,empname,sal FROM emp; -- 显示部分行: SELECT * FROM emp where sal>2000; -- 显示部分列,部分行: SELECT empno,empname,sal FROM emp where sal>2000; -- 起别名: SELECT empno 员工编号,empname 姓名,sal 工资 FROM emp; SELECT empno as 员工编号,empname as 姓名,sal as 工资 FROM emp; -- 在别名中有特殊符号的时候,''或者""不可以省略不写 SELECT empno as '员工编号',empname as "姓名",sal as 工资 FROM emp; -- 算数运算符: SELECT empno,empname,sal,sal+1000 涨薪后,deptno FROM emp where sal>2000; SELECT * FROM emp; -- 去重操作: SELECT job FROM emp; SELECT DISTINCT job FROM emp; SELECT DISTINCT job,deptno FROM emp;-- 对后面的所有列组合去重,而不是单独的某一列去重 -- 排序: SELECT * FROM emp order by sal; -- 默认情况下按照升序排列 SELECT * FROM emp order by sal asc;-- 升序 SELECT * FROM emp order by sal desc;-- 降序 SELECT * FROM emp order by sal asc,deptno desc;-- 在工资升序的情况下,deptno按照降序排列
4.2.2where子句
-- 查看emp表 SELECT * FROM emp; -- where子句:将过滤条件放在where子句的后面,可以筛选/过滤出我们想要的复合条件的数据 -- where子句 + 关系运算符 SELECT * FROM emp WHERE deptno = 10; SELECT * FROM emp WHERE deptno >= 10; SELECT * FROM emp WHERE deptno <= 10; SELECT * FROM emp WHERE deptno <> 10;-- 不等于 SELECT * FROM emp WHERE deptno != 10;-- 不等于 SELECT * FROM emp WHERE job ='clerk';-- 默认情况下不区分大小写 SELECT * FROM emp WHERE BINARY job ='clerk';-- binary区分大小写 SELECT * FROM emp WHERE BINARY hiredate ='1981-12-25'; -- where子句 +逻辑运算符 and SELECT * FROM emp where sal>1500 and sal< 2500;-- (1500,3000) SELECT * FROM emp where sal>1500 && sal< 2500;-- (1500,3000) SELECT * FROM emp where sal>1500 and sal< 2500 ORDER BY sal; SELECT * FROM emp where BETWEEN 1500 and 3000 ORDER BY sal;-- [1500,3000] -- where子句 +逻辑运算符 or SELECT * FROM emp where deptno = 10 or deptno = 20; SELECT * FROM emp where deptno = 10 || deptno = 20; SELECT * FROM emp where deptno in (10,20) ; -- where子句 + 模糊查询 -- 查询名字中带A的员工 -- %代表任意多个字符 0,1,2,...... SELECT * FROM emp WHERE empname LIKE '%A%'; -- 这个_代表任意一个字符 SELECT * FROM emp WHERE empname LIKE '_A%'; SELECT * FROM emp WHERE empname LIKE '__A%'; -- 关于null的判断: SELECT * FROM emp WHERE comm is null; SELECT * FROM emp WHERE comm is not null; -- 关于小括号的使用: SELECT * FROM emp WHERE (deptno = 10 or deptno = 20) and sal >2000; SELECT * FROM emp WHERE deptno = 10 or deptno = 20 and sal >2000;-- 先and 再 or and 的优先级比or要高
4.2.3函数
PS:除了多行函数(max,min,count,sum,avg)除了这五个以外,都是单行函数
4.2.3.1单行函数
-- 单行函数包含: -- 1.字符串函数:substring字符串截取,2:从字符下标2开始,3:截取长度3 (下标从1开始) SELECT empname,length(ename),substring(empname,2,3) FROM emp; -- 2.数值函数:abs取绝对值 ceil向上取整 floor向下取整 round四舍五入 SELECT abs(-5),ceil(5.3),FLOOR(5.9),ROUND(3.14) FROM DUAL; -- dual实际上是一个伪表 SELECT abs(-5) 绝对值,ceil(5.3)向上取整,FLOOR(5.9)向下取整,ROUND(3.14)四舍五入; -- 如果没有where条件的话,from dual可以省略不写 SELECT ceil(sal) FROM emp; SELECT 10/3,10%3,MOD(10,3); -- 3.日期和时间函数 SELECT * FROM emp; SELECT CURDATE(),CURTIME();-- CURDATE()年月日 CURTIME()时分秒 SELECT NOW(),SYSDATE(),SLEEP(3),NOW(),SYSDATE();-- NOW()返回当前日期和时间 SYSDATE返回该函数执行时的日期和时间 -- NOW()可以表示年月日时分秒,但是插入数据的时候还是要参照表的结构 -- 4.流程函数 -- if相关 SELECT empno,empname,sal,IF(sal>=2500,'高薪','低薪')薪资等级 FROM emp;-- if ELSE 双分支结构 SELECT empno,empname,sal,comm,sal+IFNULL(comm,0) FROM emp;-- 如果comm是null,那么取值为0 -- 单分支 SELECT NULLIF(1,1),NULLIF(1,2); -- 如果value1等于value2,则返回null,否则返回value1 -- case相关:case等值判断 SELECT empno,empname,job, CASE job when 'CLERK' then '店员' else '其他' end 岗位, sal FROM emp; -- case区间判断 SELECT empno,empname,job, CASE job when sal<=1000 then 'A' when sal<=2000 then 'B' when sal<=3000 then 'C' else 'D' end 工资等级, deptno FROM emp; -- 5.JSON函数 -- 6.其他函数 -- DATABASE()当前数据库是啥 USER()使用者是谁 VERSION()对应的数据库的版本 SELECT DATABASE(),USER(),VERSION() ;
4.2.3.2多行函数
-- 单行函数包含: -- 1.字符串函数:substring字符串截取,2:从字符下标2开始,3:截取长度3 (下标从1开始) SELECT empname,length(ename),substring(empname,2,3) FROM emp; -- 2.数值函数:abs取绝对值 ceil向上取整 floor向下取整 round四舍五入 SELECT abs(-5),ceil(5.3),FLOOR(5.9),ROUND(3.14) FROM DUAL; -- dual实际上是一个伪表 SELECT abs(-5) 绝对值,ceil(5.3)向上取整,FLOOR(5.9)向下取整,ROUND(3.14)四舍五入; -- 如果没有where条件的话,from dual可以省略不写 SELECT ceil(sal) FROM emp; SELECT 10/3,10%3,MOD(10,3); -- 3.日期和时间函数 SELECT * FROM emp; SELECT CURDATE(),CURTIME();-- CURDATE()年月日 CURTIME()时分秒 SELECT NOW(),SYSDATE(),SLEEP(3),NOW(),SYSDATE();-- NOW()返回当前日期和时间 SYSDATE返回该函数执行时的日期和时间 -- NOW()可以表示年月日时分秒,但是插入数据的时候还是要参照表的结构 -- 4.流程函数 -- if相关 SELECT empno,empname,sal,IF(sal>=2500,'高薪','低薪')薪资等级 FROM emp;-- if ELSE 双分支结构 SELECT empno,empname,sal,comm,sal+IFNULL(comm,0) FROM emp;-- 如果comm是null,那么取值为0 -- 单分支 SELECT NULLIF(1,1),NULLIF(1,2); -- 如果value1等于value2,则返回null,否则返回value1 -- case相关:case等值判断 SELECT empno,empname,job, CASE job when 'CLERK' then '店员' else '其他' end 岗位, sal FROM emp; -- case区间判断 SELECT empno,empname,job, CASE job when sal<=1000 then 'A' when sal<=2000 then 'B' when sal<=3000 then 'C' else 'D' end 工资等级, deptno FROM emp; -- 5.JSON函数 -- 6.其他函数 -- DATABASE()当前数据库是啥 USER()使用者是谁 VERSION()对应的数据库的版本 SELECT DATABASE(),USER(),VERSION() ; -- 多行函数 SELECT max(sal),min(sal),count(sal),sum(sal),avg(sal) FROM emp; -- 多行函数会自动忽略null值 SELECT max(comm),min(comm),count(comm),sum(comm),avg(comm) FROM emp; -- max(), min(), count() 针对所有类型 sum(),avg() 只针对数值类型有效 -- count -- 计数 -- 统计表的记录数:方式1 SELECT * FROM emp; SELECT count(*) FROM emp; -- 方式2 SELECT 1 FROM dual; SELECT 1 FROM emp; SELECT count(1) FROM emp;
4.2.4 group by分组和having筛选
【1】group by:用来进行分组
【2】sql展示:
-- 统计各个部门的平均工资 SELECT deptno,avg(sal) FROM emp; -- 字段和多行函数不能同时使用 SELECT deptno,avg(sal) FROM emp GROUP BY deptno ORDER BY deptno desc; -- 字段和多行函数不能同时使用,除非这个字段属于分组 -- 统计各个部门的平均工资 SELECT job,avg(sal) FROM emp GROUP BY job;
【3】having:进行分组后的筛选
【4】sql展示:
-- 统计各个部门的平均工资,只显示平均工资2000以上的 分组以后进行二次筛选 SELECT deptno,avg(sal) FROM emp GROUP BY deptno HAVING avg(sal)>2000; SELECT deptno,avg(sal) 平均工资 FROM emp GROUP BY deptno HAVING 平均工资>2000; SELECT deptno,avg(sal) 平均工资 FROM emp GROUP BY deptno HAVING 平均工资>2000 ORDER BY deptno desc; -- 统计各个岗位的平均工资,除了MANAGER -- 方法1 SELECT job,AVG(sal) FROM emp where job !='MANAGER' GROUP BY job; -- 方法2 SELECT job,AVG(sal) FROM emp GROUP BY job HAVING job!='MANAGER'; -- where 在分组前进行过滤的,having是在分组后进行过滤的
4.2.5 单表查询总结
【1】select语句总结
【2】select语句的执行顺序
【3】单表查询练习:
-- 单表查询练习: -- 列出工资最小值小于2000的职位 SELECT job,MIN(sal) FROM emp GROUP BY job HAVING MIN(sal)<2000; SELECT * FROM emp; SELECT * FROM dept; -- 列出平均工资大于1200元的部门和工作搭配组合 SELECT deptno,job,AVG(sal) FROM emp GROUP BY deptno,job HAVING AVG(sal)>1200 ORDER BY deptno; -- 统计[人数小于4的]部门的平均工资。 SELECT deptno,AVG(sal) FROM emp GROUP BY deptno HAVING COUNT(deptno)<4; -- 统计各部门的最高工资,排除最高工资小于3000的部门。 SELECT deptno,MAX(sal) FROM emp GROUP BY deptno HAVING MAX(sal)>=3000;
4.3多表查询
4.3.1交叉连接,自然连接,内连接
-- 查询员工得编号,姓名,部门编号: SELECT * FROM emp; SELECT empno,empname,deptno FROM emp; -- 查询员工得编号,姓名,部门编号,部门名称: SELECT * FROM emp; -- 14条记录 SELECT * FROM dept; -- 4条记录 -- 多表查询: -- 交叉链接:cross join SELECT * FROM emp cross join dept; -- 14*4 = 56条 笛卡尔乘积: 没有实际意义,有理论意义 -- 自然链接:natural join -- 优点:自动匹配所有的同名列, 同名列只展示一次,简单 SELECT * FROM emp NATURAL join dept; -- 缺点:查询字段的时候,没有指定字段所属的数据库表,效率低 -- 解决:指定表名 SELECT emp.empno,emp.empname,dept.deptno FROM emp NATURAL JOIN dept; -- 缺点:表名太长咋办啊 -- 解决:表可以起别名 SELECT e.empno,e.empname,d.deptno FROM emp e NATURAL JOIN dept d; -- 自然链接natural join 的缺点:自动表中的匹配所有的同名列。但是有时候我们只希望匹配部分同名列 -- 解决:内连接 - using子句 SELECT * FROM emp inner join dept -- inner 内连接 using(deptno); -- 这里不能写natural join了,这里是内连接 -- using缺点:关联的字段,必须是同名的 -- 解决:内连接的里面的on子句 SELECT * FROM emp e inner join dept d on (e.aaa = d.bbb); -- 多表链接查询的类型: /* 1.交叉链接 cross join 2.自然链接 natural join 3.内连接 - using子句 4.内连接 - on子句 综合看 内连接 - on子句用的最多 */ -- 条件: /* 1.筛选条件 where having 2.连接条件 on,using,natural,cross SQL99语法: 筛选条件和连接条件是分开的 */
4.3.2外连接
-- inner join - on 子句: 显示的是所有匹配的信息 -- 外连接:除了显示匹配的数据之外,还可以显示部门或者全部不匹配的数据 -- 左外连接: left outer join --左面哪个表的信息,即使不匹配也可以查看出效果 SELECT * FROM emp e left join dept d on e.deptno = d.deptno; -- 右外连接: right outer join --右面哪个表的信息,即使不匹配也可以查看出效果 SELECT * FROM emp e right outer join dept d on e.deptno = d.deptno ; -- 全外连接 SELECT * FROM emp e left join dept d on e.deptno = d.deptno union -- 并集 去重 效率低 SELECT * FROM emp e right outer join dept d on e.deptno = d.deptno; SELECT * FROM emp e left join dept d on e.deptno = d.deptno union all -- 并集 不去重 效率高 SELECT * FROM emp e right outer join dept d on e.deptno = d.deptno ;
4.3.3三表连接查询
4.3.4自连接
想象成两张表。
4.4子查询
【1】什么是子查询?
一条SQL语句含有多个select
【2】执行顺序:
先执行子查询,再执行外查询
【3】不相关子查询:
子查询可以独立运行,称为不相关子查询。
【4】不相关子查询分类:
根据子查询的结果行数,可以分为单行子查询和多行子查询。
4.4.1不相关子查询
4.4.1.1单行子查询
4.4.1.2多行子查询
4.4.2相关子查询
【1】相关子查询引入
【2】相关子查询的优缺点
5.数据库对象
5.1事务及其特征
事务是用来维护数据库完整性的,它能够保证一系列的MySQL操作要么全部执行,要么全不执行
【1】事务的概念
【2】事务的特性
但是不是所有的操作序列都可以成为事务,要成为事务要满足四个特性,ACID特性
【3】sql展示:
5.2事务并发问题
【1】脏读
【2】不可重复读
【3】幻读
【4】不可重复读和幻读的区别:
不可重复读的重点是修改,幻读的重点在于新增或者删除。
解决不可重复读的问题只需要锁住满足条件的行,解决幻读需要锁住表。
5.2事务隔离级别
为了解决事务的并发问题,引入了事务的并发级别。
5.3视图
【3】sql展示: