MySQL课堂查询

内容分享2周前发布
0 0 0

一.简单查询语句

1.查表内数据


SELECT * FROM emp; #员工表
SELECT * FROM dept; #部门表
SELECT * FROM student; #学生表
SELECT * FROM course; #课程表
SELECT * FROM score; #成绩表
SELECT * FROM salgrade;#工资等级表

2.查询员工工号,姓名,职位


SELECT empno,ename,job FROM emp;

3.查询工号,姓名,工资以及工资加500之后工资;


SELECT empno,ename,sal,sal+500 FROM emp;

4.查询员工的工资,奖金和工资与奖金和;


SELECT ename,sal,com,sal+comm form emp;

5.AS改列名


#查询员工姓名与年薪
SELECT ename AS 姓名,sal*12 AS 年薪 FROM emp;

#修改为含有空格的列名
SELECT ename AS 姓名,sal*12 AS '年  薪' FROM emp;

6.简单算术运算


SELECT 25*40;
SELECT "hello",'1999-12-12';

7.Distinct去重


#部门编号和工作去重
SELECT DISTINCT deptno,job FROM emp;

8.where语句


#部门号为10 的员工
SELECT * FROM emp WHERE deptno=10;

#职位是salesman的员工
SELECT * FROM emp WHERE job='SALESMAN';

#入职日期是1980-12-17的员工
SELECT * FROM emp WHERE hiredate='1980-12-17';

#查询工资大于等于1500
SELECT * FROM emp WHERE sal>=1500;

#查询工资小于等于3000
SELECT * FROM emp WHERE sal<=3000;

#查询职位不是cleck的员工
SELECT * FROM emp WHERE job<>'cleck'; #不等于<>

#查询奖金比工资高的员工
SELECT * FROM emp WHERE comm>sal;

9.Between and


#查询工资在1500和3000之间的员工
SELECT * FROM emp WHERE sal BETWEEN 1500 AND 3000;

#查询1981年入职的员工
SELECT * FROM emp WHERE hiredate BETWEEN '1981-01-01' AND '1981-12-31';
#知道日期格式的情况下
SELECT * FROM emp WHERE hiredate LIKE '1981%';

10.In用法


#查询工资是1500或者3000的员工
SELECT * FROM emp WHERE sal IN (1500,3000);

11.通配符%和_


#0个或者任意多个字符
#_一个字符
#查询姓张的同学
SELECT * FROM student WHERE sname LIKE'张%';
#查询名字第二个字是小的同学
SELECT * FROM student WHERE sname LIKE'_小%';
#查询名字最后一个字是文的同学
SELECT * FROM student WHERE sname LIKE'%文';

12.转义符


#查询名字最后是%的同学,放在想转换的字符前面
SELECT * FROM student WHERE sname LIKE'%\%';

13.Null


#查询奖金为null的员工
SELECT * FROM emp WHERE comm IS NULL;
#查询奖金不为null的员工
SELECT * FROM emp WHERE comm IS NOT NULL;

14.And 和 Or


#查询部门10工资大于1500的员工
SELECT * FROM emp WHERE sal>1500 AND deptno=10;
#查询部门10或者工资大于1500的员工
SELECT * FROM emp WHERE sal>1500 OR deptno=10;

#查询部门10和部门20的员工
SELECT * FROM emp WHERE deptno=10 OR deptno=20;
SELECT * FROM emp WHERE deptno IN(10,20);

15.Not的用法


#直接将判定条件反转
SELECT * FROM emp WHERE NOT 1=1;

#查询工资不在1500和3000之间的员工
SELECT * FROM emp WHERE NOT sal BETWEEN 1500 AND 3000;
#查询不信张的同学
SELECT * FROM student WHERE sname NOT LIKE '张%';
#查询部门号不是10也不是20的员工
SELECT * FROM emp WHERE NOT deptno IN(10,20);

16.优先级问题


#查询部门号是10,和部门号为20且工资大于1500的
SELECT * FROM emp WHERE deptno=10 OR deptno=20 AND sal>1500;
#查询部门号是10和部门号为20且工资都大于1500的
SELECT * FROM emp WHERE (deptno=10 OR deptno=20) AND sal>1500;

17.Order by 排序


#desc降序,asc升序(不写默认升序)
#查询emp表,显示奖金不为空或者部门号为20的雇员信息,要求按照薪水降序排列
SELECT * FROM emp WHERE comm IS NOT NULL OR deptno=20 ORDER BY sal DESC;

#查询emp表,显示年薪大于30000,工作类别不是MANAGER,且部门号不是10或40(既不是10,也不是40)的雇员信息
#要求按照雇员姓名进行排列
SELECT * FROM emp WHERE sal*12>30000 
AND job<>'Manager' 
AND deptno NOT IN(10,40) 
ORDER BY ename;

#入职日期最早到最晚排序
SELECT * FROM emp ORDER BY hiredate;

双列排序注意


#查询员工信息,按照部门号升序,工资降序
SELECT * FROM emp ORDER BY deptno,sal DESC;
#第一列没有重复的数据,第二列数据将毫无意义
#所以先部门号,再工资

18.别名排序


#年薪倒序查询
SELECT ename,sal*12 FROM emp ORDER BY sal12 DESC;
#年薪倒序查询
SELECT ename,sal*12 年薪 FROM emp ORDER BY 年薪 DESC;

不能使用列的别名在where语句

执行顺序

fromwhereselect 定义别名order by

19.Limit


SELECT * FROM emp LIMIT 0,3;
SELECT * FROM emp LIMIT 3;# 0可以省略
SELECT * FROM emp LIMIT 2,3;#从第三行显示三行

#查询公司最高工资
SELECT * FROM emp 
ORDER BY sal DESC
LIMIT 1;

#写零默认整数
SELECT ROUND(123.45,1), ROUND(123.454);

20.Round函数


#查询员工姓名,日薪,保留两位,
SELECT ename ,ROUND (sal/22,2) FROM emp;

21.大小写转换


SELECT UPPER('adcd'),LOWER('abcd')

#查询员工姓名,显示小写字母
SELECT LOWER(ename) FROM emp;

22.拼接字符串(后面会用)


SELECT CONCAT('test','mysql');
SELECT ename, job FROM emp;
SELECT CONCAT(ename,' is a ',job) FROM emp;

23.Length长度函数


#1个英文字符占1个字节
#1个中文字符占3个字节
SELECT LENGTH('test'),CHAR_LENGTH('test');
SELECT LENGTH('汉字'),CHAR_LENGTH('三个');

24.Left,Right函数


#从abcde左取三个,abcde右取两个
SELECT LEFT('adcde',3),RIGHT('adcde',2);

查找姓张的
SELECT * FROM student WHERE LEFT(sname,1)='张';
SELECT * FROM student WHERE RIGHT(sname,1)='文';

25.Mid,Subtr,Subtring函数


SELECT MID('abcdefg',2,4),
       SUBSTR('abcdefg',2,4),
       SUBSTRING('abcdefg',2);
#从第二个开始,只取一个
SELECT * FROM student WHERE MID(sname,2,1)='小';

26.IFNull


#不为空输出NULL,为空输出10
SELECT IFNULL(NULL,10);
SELECT ename,sal,comm, IFNULL(comm,0),sal+comm FROM emp;

27.IF函数


SELECT ename,sal,IF(sal>5000,'富','穷') FROM emp;

28.日期函数Month()


#查询2月入职的员工
SELECT * FROM emp WHERE MONTH(hiredate)=02;
#格式必须提前知道
SELECT * FROM emp WHERE hiredate LIKE '____-02%';

29.Datediff()


#获取天数差值
SELECT DATEDIFF('2025-10-18','2025-10-01');

#查询每个员工的工作年限
SELECT ename,DATEDIFF(CURDATE(),hiredate)/365,
YEAR(CURDATE())-YEAR(hiredate)
FROM emp;

30.当前日期函数


#获取当前日期
SELECT 
CURDATE(),
CURTIME(),
NOW();
#获取当前年月日
SELECT 
YEAR('1997-7-1'),
MONTH('1997-7-1'),
DAY('1997-7-1');

二.多表查询


#查询员工工号,姓名,部门号,部门地址;
/*  思路
1.生成笛卡尔乘积
select * from emp,dept; 
2.添加连接条件,
目的是从笛卡尔乘积中过滤有效数据
select * from
*/
SELECT empno,ename,emp.deptno,loc 
FROM emp,dept 
WHERE 
emp.deptno
=dept.deptno;

1.等值连接:连接条件使用等号

2.不等连接:连接条件使用处理等号以外的比较符号


#查询名字为King的员工编号,员工名,部门编号和部门地址
SELECT empno,ename,e.deptno,loc 
FROM emp e,dept d
WHERE 
e.deptno=d.deptno 
AND ename='king';

#查询学生的课程成绩
SELECT s.sname,c.cname,sc.grade
FROM student s,score sc,course c
WHERE 
s.sid=sc.sid 
AND sc.cid=c.cid;

#找出选修了“LoadRunner”课程但成绩低于80分的学生姓名。
SELECT s.sname,c.cname,sc.grade
FROM student s,score sc,course c
WHERE 
s.sid=sc.sid AND sc.cid=c.cid
AND c.cname='LoadRunner'
AND sc.grade<80;

3.不等连接


#员工的姓名,工资和工资等级
SELECT e.ename,e.sal,sal.grade
FROM emp e,salgrade sal
WHERE e.sal 
BETWEEN sal.losal AND sal.hisal;

按照连接的表是否是一个表自连接:将一个表看成多个表进行连接非自连接:不同表进行连接

4.自连接


#查询员工的姓名及其主管的姓名
SELECT w.ename 员工,m.ename 主管
FROM emp w,emp m
WHERE w.mgr=m.empno;

#查询入职日期比自己的主管早的员工
SELECT *
FROM emp w,emp m
WHERE 
w.mgr=m.empno 
#要先判断主管和员工,再比较
AND w.hiredate<m.hiredate;

5.内连接(inner join)

–满足连接条件的记录


#查询员工的姓名及其主管的姓名
#ISO99标准
SELECT w.ename 员工,m.ename 主管
FROM emp w JOIN emp m
ON w.mgr=m.empno;

6.外连接(outer join)

–将不满足连接条件的记录也显示出来。ps没有主管也显示

7.左外连接(left join)


#查询员工的姓名及其主管的姓名,将没有主管的也显示出来
SELECT w.ename 员工,m.ename 主管
FROM emp w LEFT JOIN emp m
ON w.mgr=m.empno;

8.右外连接(right join)

9.全外连接(left join)


#插入一名员工
INSERT INTO emp(empno,ename,job,sal)
VALUES(7901,'JACK','CLERK',3500);

#查询员工员工的工号,姓名,部门,部门地址
SELECT e.empno,e.ename,e.deptno,d.loc
FROM emp e JOIN dept d
ON e.deptno=d.deptno;

#查询员工员工的工号,姓名,部门,部门地址
#没有员工的部门也查询出来
SELECT e.empno,e.ename,d.deptno,d.loc
FROM emp e RIGHT JOIN dept d
ON e.deptno=d.deptno;

#查询员工员工的工号,姓名,部门,部门地址
#没有部门的员工也查询出来
SELECT e.empno,e.ename,e.deptno,d.loc
FROM emp e LEFT JOIN dept d
ON e.deptno=d.deptno;

#删除刚插入的一行
DELETE FROM emp WHERE empno=7901;

#查询工资等级为3/4/5级的员工姓名
#工资,工资等级,工资等级升序
SELECT e.ename,e.sal,sal.grade
FROM emp e,salgrade sal
WHERE e.sal 
BETWEEN sal.losal AND sal.hisal 
AND sal.grade IN (3,4,5)
ORDER BY sal.grade;

#列出主管的名字。
SELECT DISTINCT m.ename  #去重
FROM emp w RIGHT JOIN  emp m
ON w.mgr=m.empno;

#列出部门名称和这些部门的员工信息,
#同时列出那些没有员工的部门。
SELECT d.dname,e.* 
FROM emp e RIGHT JOIN dept d
ON e.deptno=d.deptno;

#列出成绩高于80分的学生姓名、课程名称和成绩。
SELECT st.sname,c.cname,s.grade
FROM student st,score s,course c
WHERE
st.sid=s.sid 
AND s.cid=c.cid
AND s.grade>80;

#查询公司的平均工资,最高工资,最低工资
SELECT 
AVG(sal),MAX(sal),MIN(sal),SUM(sal)
FROM emp;

#查询manager的平均工资,最高工资,最低工资
SELECT 
job,AVG(sal),MAX(sal),MIN(sal),SUM(sal)
FROM emp
WHERE job='manager';

#最早晚的入职日期
SELECT MIN(hiredate),MAX(hiredate)
FROM emp;

10.COUNT函数


#count不统计空值
#count统计重复值
SELECT
COUNT(empno),COUNT(comm),
COUNT(DISTINCT deptno),
COUNT(*) 
FROM emp;

11.AVG函数


#avg不统计空值
#查询平均佣金
SELECT 
AVG(comm),#非null/非NULL
SUM(comm)/14,#非null/14
AVG(IFNULL(comm,0))#(非null+0*null员工)/14
FROM emp;

12.分组函数

——出现在select后面的列,必须是group by的列或者聚合函数


#查询每个部门的平均工资
#逻辑
#1. FROM子句:首先从 emp 表中获取所有数据行,这是查询的数据源。
#2. GROUP BY子句:将 emp 表中的数据按照 deptno (部门编号)进行分组,相同 deptno 的行被归为一组。
#3. 聚合计算(AVG(sal)):对每个分组内的 sal (工资)字段执行 AVG() 函数,计算每组的平均工资。
#4. SELECT子句:从分组后的结果中选取 deptno (分组依据字段)和计算得到的平均工资 AVG(sal) ,作为最终结果集返回。
SELECT deptno,AVG(sal) 
FROM emp 
GROUP BY deptno;

#查询每个职位的平均工资
SELECT job,AVG(sal) 
FROM emp
GROUP BY job;

#查询学生表中每个年龄的人数
SELECT sage,COUNT(sage) FROM student 
GROUP BY sage;

#查询学生表中男生和女生的人数
SELECT ssex,COUNT(*) FROM student 
GROUP BY ssex;

#查询学生表中每个年龄的人数男生和女生的人数
SELECT sage,ssex,COUNT(*)
FROM student
GROUP BY sage,ssex;

#查询每个部门的人数
SELECT deptno,COUNT(empno)
FROM emp
GROUP BY deptno;

#查询每个部门的人数
#没有员工的部门也输出
SELECT d.deptno,COUNT(empno)
FROM emp e RIGHT JOIN dept d
ON e.deptno=d.deptno
GROUP BY d.deptno;

#查询每个职位的人数
SELECT job,COUNT(empno)
FROM emp
GROUP BY job;

#查询每个部门中每种职位的人数
SELECT deptno,job,COUNT(empno)
FROM emp
GROUP BY deptno,job;

#查询每年入职人数
SELECT DISTINCT YEAR(hiredate),
COUNT(empno)
FROM emp
GROUP BY YEAR(hiredate);

#出现在select后面的列,必须是groupby的列或者聚合函数
SELECT deptno,MAX(sal) FROM emp 
GROUP BY deptno,job;
SELECT ename,SUM(sal) FROM emp;

13.分组过滤Having


#查询平均工资大于1500的职位
SELECT job,AVG(sal) FROM emp
GROUP BY job
HAVING AVG(sal)>1500;

#where 和 having的区别
/*
1.where对行进行过滤,having对分组进行过滤
2.where不能使用分组函数,
having可以使用分组函数
*/

三.子查询


#查询工资高于jones的工资
SELECT * 
FROM emp
WHERE sal>(
SELECT sal FROM emp 
WHERE ename='JONES');

#查询工资最高的员工
SELECT *
FROM emp
WHERE  sal=
(SELECT MAX(sal) FROM emp);

#查询工资高于公司平均工资的员工
SELECT *
FROM emp
WHERE  sal>
(SELECT AVG(sal) FROM emp);

#查询平均工资高于salsman的平均工资的职位
SELECT job,AVG(sal)
FROM emp
GROUP BY job
having AVG(sal)>
(SELECT AVG(sal) FROM emp 
WHERE job='salesman');

#查询有员工的部门号,部门名和部门地址
SELECT *FROM dept
WHERE deptno 
IN(SELECT deptno FROM emp);

#查询没有员工的部门号,部门名,和部门地址
SELECT *FROM dept
WHERE deptno 
NOT IN(SELECT deptno FROM emp);

#查询工资比部门20所有人都高的员工
#单行子查询
SELECT * FROM emp WHERE sal>
(SELECT MAX(sal) 
FROM emp 
WHERE deptno=20);
#多行子查询
SELECT * FROM emp WHERE sal>
ALL(SELECT sal
FROM emp 
WHERE deptno=20);

#查询工资比部门20工资最低的人都高的员工
SELECT * FROM emp WHERE sal>
(SELECT MIN(sal) 
FROM emp 
WHERE deptno=20);


SELECT * FROM emp WHERE sal>
ALL(SELECT MIN(sal)
FROM emp 
WHERE deptno=20);

SELECT * FROM emp WHERE sal>
(SELECT sal
FROM emp 
WHERE deptno=20);

#查询部门号和职位都跟simth相同的员工
SELECT * FROM emp WHERE deptno=(
SELECT deptno FROM emp WHERE ename='smith')
AND 
job=(
SELECT job 
FROM emp WHERE ename='smith');

练习


#列出薪金比“SMITH”多的所有员工。
SELECT * FROM emp
WHERE sal>(
SELECT sal FROM emp
WHERE ename='SMITH');

#列出在部门“SALES”(销售部)工作的员工的姓名,假定不知道销售部的部门编号。
SELECT ename FROM emp 
WHERE deptno=(
SELECT deptno FROM dept 
WHERE dname='SALES');

#列出与“SCOTT”从事相同工作的所有员工。
SELECT * FROM emp 
WHERE job=(
SELECT job FROM emp 
WHERE ename='scott');

#查询在NEW YORK工作并且工资比'SCOTT'高的职员的名字、职业、工资
SELECT ename,job,sal FROM emp
WHERE deptno=(SELECT deptno FROM dept WHERE loc='New york')
AND sal>(SELECT sal FROM emp 
WHERE ename='scott');

#查询叶玉娟的测试基础这门课成绩
SELECT s.grade FROM score s,course c
WHERE s.cid=c.cid
AND c.cname='测试基础'
AND s.sid =(SELECT sid FROM student WHERE sname='叶玉娟');

SELECT grade FROM score 
WHERE sid=(SELECT sid FROM student WHERE 
sname='叶玉娟')
AND cid=(SELECT cid FROM course WHERE cname
='测试基础');

#查询最高的部门平均工资
SELECT MAX(avgsal) FROM( 
SELECT deptno,AVG(sal) avgsal FROM emp 
GROUP BY deptno) t;

UNION连接


SELECT* FROM emp WHERE deptno=10
UNION#去重 显示3+5=8个结果
SELECT * FROM emp WHERE deptno<=20;

SELECT* FROM emp WHERE deptno=10
UNION ALL# 不去重 显示3+3+5=11个结果
SELECT * FROM emp WHERE deptno<=20;

CASE WHEN ELSE END


#根据员工不同的 
#第一种用法
SELECT ename,job,CASE job
WHEN 'clerk' THEN'办事员'
WHEN 'salesman'THEN'销售员'
WHEN'manager'THEN'经理'
ELSE '其他岗'
END '岗 位'
FROM emp;

#第二种用法
SELECT sid,cid grade,CASE
WHEN grade >=90 THEN 'A'
WHEN grade >=80 THEN 'B'
WHEN grade >=70 THEN 'C'
ELSE 'D'
END 等级 
FROM score
ORDER BY 等级;

#查询学生姓名,性别为M显示男,F的显示女
#年龄,年龄大于30,显示中年
#年龄大于25,显示壮年
#大于18,显示青年
#小于18 显示未成年
#多注意Case前的符号
SELECT sname,ssex, CASE 
WHEN ssex='M' THEN'男'
ELSE '女'
END 性别,
sage,CASE 
WHEN sage >=30 THEN '中年'
WHEN sage >=25 THEN '壮年'
WHEN sage >=18 THEN '青年'
ELSE '未成年'
END 年纪
FROM student;

四.数据操作语句

DML语句

insert语句


INSERT INTO dept(deptno,dname,loc)
VALUES (50,'test50','NJ');
#重复就会报错,因为deptno是主键,不能重复
INSERT INTO dept(deptno,dname)
VALUES (60,'test60');
#正确写法

INSERT INTO dept VALUES(70,'test70');
#报错,不指定列名,每个字段必须填数据
INSERT INTO dept VALUES (70,'test70',NULL);
#正确写法

#插入日期
INSERT INTO emp(empno,ename,hiredate)
VALUES(7777,'zhangsan','1997-7-1');

#插入员工李四,入职日期为现在日期
INSERT INTO emp(empno,ename,hiredate)
VALUES(9999,'李四',NOW());
SELECT * FROM emp;

#一次插入多条记录
INSERT INTO dept(deptno,dname,loc)
VALUES 
(71,'test71','BJ'),
(72,'test72','SH'),
(73,'test73','GZ');

修改


#将部门号为50的地址改为苏州
UPDATE dept 
SET loc='苏州'
WHERE deptno=50;

#一次可以修改多列
#部门60改为测试部
#部门搬到深圳
UPDATE dept SET dname='测试部',loc='深圳'
WHERE deptno=60;

使用子查询修改


#将Smith的工作地修改到深圳
UPDATE emp
SET deptno=(
SELECT deptno 
FROM dept 
WHERE loc='深圳')
WHERE ename='smith';

#将Smith的部门号修改的和King一样
#mysql规定
#修改的表和子查询的表不能是同一个
UPDATE emp
SET deptno=(
SELECT deptno
FROM (SELECT *FROM emp) t
WHERE ename='king')
WHERE ename='smith';

删除


DELETE FROM dept WHERE deptno=50;
DELETE FROM dept WHERE deptno>70;

#先删除dept表,才能删emp表,因为外键需要参考
DELETE FROM dept;
DELETE FROM emp;#可以删

事务

#默认情况下,MySQL是自动提交事务的

#所有用户都能看到添加的记录

BEGIN-COMMIT


SELECT * FROM dept;
INSERT INTO dept(deptno,dname,loc)
VALUES (80,'test80','NJ');

#开启手动提交,只有执行commit才会提交事务
BEGIN#先begin
INSERT INTO dept(deptno,dname,loc)
VALUES (90,'test90','YC');
COMMIT#最后提交才能看到

ROLLBACK


BEGIN
DELETE FROM emp;
ROLLBACK;#回滚

练习


#在EMP表中,增加一名员工,员工信息参照现有员工构造.
SELECT * FROM emp;
INSERT INTO emp(empno,ename,job,hiredate,sal,deptno)
VALUES (8888,'XCP','TESTER','2025-05-20',20000,10);

#员工SMITH部门调动到SALES部门,请编写SQL语句更新员工信息.
UPDATE emp SET deptno=(
SELECT deptno FROM dept WHERE dname='sales')
WHERE ename='smith';

#员工JAMES已经离职,请编写SQL语句更新数据库.
DELETE FROM emp WHERE ename='JAMES';

#将叶玉娟的测试基础这门课成绩修改为60分
UPDATE score SET grade=60
WHERE cid=(SELECT cid FROM course 
WHERE cname='测试基础')
AND sid=(SELECT sid FROM student 
WHERE sname='叶玉娟');

#夏晓燕转学,将夏晓燕的全部信息删除
DELETE FROM score
WHERE sid=(
SELECT sid FROM student
WHERE sname='夏晓燕');

DELETE FROM student WHERE 
sname='夏晓燕';

创建数据库


CREATE DATABASE school;

删数据库


DROP DATABASE school;

CREATE TABLE teacher
(
    tid INT PRIMARY KEY,
    tname VARCHAR(30),
    tage TINYINT UNSIGNED,
    tsex CHAR(1) DEFAULT '男',
    tsal DECIMAL(7,2),
    hiredate DATE
)

DESC查看表结构


DESC teacher;

SHOW查看建表语句


#查看建表语句
SHOW CREATE TABLE teacher;

测试浮点数和定点数


CREATE TABLE test1
(
         id1 FLOAT(7,2),
         id2 DOUBLE(7,2),
         id3 DECIMAL(7,2)
 )
 
INSERT INTO test1
VALUES (3.14,3.14,3.14);
#均显示3.14

SELECT id1+3.14,id2+3.14,id3+3.14
FROM test1;
#均显示6.28

SELECT id1*3.14,id2*3.14,id3*3.14
FROM test1;
#9.86,9.86,9.8596
/*
原因:
1. 类型的存储特性
- FLOAT(单精度浮点型)/DOUBLE(双精度浮点型):
采用“近似值存储”,通过二进制浮点表示法存储数据,无法精准表示所有十进制小数(比如 3.14 这类小数转二进制是无限循环的),计算后会自动对结果进行近似舍入,所以显示为 9.86 。
- DECIMAL(定点型):
采用“精确值存储”,以字符串形式存储十进制数字,能精准表示小数,计算时不会丢失精度,因此保留了更详细的 9.8596 。
2. 显示规则的影响
MySQL客户端默认会对浮点型(FLOAT/DOUBLE)的结果进行自动格式化显示(通常与字段定义的精度一致,比如 (7,2) 会显示两位小数),而DECIMAL会保留计算后的实际精度。
*/

#插入一名教师不指定性别
INSERT INTO teacher(tid,tname)
VALUES(1000,'王晓红');
SELECT * FROM teacher;

INSERT INTO teacher(tid,tname,tsal)
VALUES(1001,'王红',12345.11);

INSERT INTO teacher(tid,tname,tsal)
VALUES(1002,'王晓',123.231231);
#警告,四舍五入

自增AUTO_INCREMENT


#创建学生表school
CREATE TABLE student
(
     sid INT AUTO_INCREMENT PRIMARY KEY,
     sname VARCHAR(30),
     ssex CHAR(1) DEFAULT '男',
     sage TINYINT UNSIGNED
)
#查看表结构
DESC student;

#自增的作用,先插入,再插入变成9001
INSERT INTO student(sid,sname,sage)
VALUES(9000,'张三',19);
INSERT INTO student(sname,sage)
VALUES('张三',19);

表数据 alter

#表数据 insert update delete
#alter直接提交,不能回滚


#增加一列 手机号
ALTER TABLE student ADD 
sphone CHAR(11)
AFTER ssex;#放在性别后面

#删除手机号列
ALTER TABLE student
DROP COLUMN sphone;

MODIFY


#修改数据类型和长度
#有数据的情况下有可能不能改,引发错误
ALTER TABLE student
MODIFY sphone VARCHAR(13);

CHANGE


#修改列名和数据类型
#将手机改为mobile 改为固定11个字符
ALTER TABLE student 
CHANGE sphone mobile CHAR(11);

Set修改默认值


ALTER TABLE student 
ALTER ssex
SET DEFAULT '女';

Drop删除默认值


ALTER TABLE student 
ALTER ssex
DROP DEFAULT;

Rename修改表名


ALTER TABLE student
RENAME TO stu;
DESC stu;

练习


#将表名改回student
ALTER TABLE stu
RENAME TO student;
DESC student;

#添加一列国籍,默认值中国,不为空
ALTER TABLE student
ADD country VARCHAR(30) 
DEFAULT '中国' NOT NULL;

#删除sage这一列
ALTER TABLE student
DROP COLUMN sage;

#增加出生日期
ALTER TABLE student
ADD birthday DATE;

order_status 表


#创建表
CREATE TABLE order_status 
(
    id INTEGER PRIMARY KEY ,
    STATUS CHAR(10),
    last_modified DATE,
    modified_by INTEGER,
    initially_created DATE NOT NULL,
    test VARCHAR(15),
    testb VARCHAR(10) DEFAULT 'testb'
)

#修改test字段
#使其不允许为空且赋予其一个默认值testing
ALTER TABLE order_status 
MODIFY test 
VARCHAR(15)#类型得写,不改也写
DEFAULT 'testing'
NOT NULL ; 

#ddl语句是定义语句,直接写到数据库,

#无法回滚

TRUNCATE删除全部记录


TRUNCATE TABLE student;
# 快速删除 炸单包赔

DROP TABLE student;

#drop truncate delete语句
/*
drop删除表记录和表结构
truncate和delete只删除表数据
drop和truncate是DDL语句,不能回滚
delete是DML语句,可以回滚
truncate只能删除全部记录,delete可以删除全部或者部分记录
truncate的效率比delete高
*/

约束


CREATE TABLE student
(
     sid INT ,
     sname VARCHAR(30) NOT NULL,
     ssex CHAR(1) DEFAULT '男',
     sage TINYINT UNSIGNED
     #check(sage between 18 and 28)
     ,
     sphone CHAR(11) UNIQUE,
     PRIMARY KEY(sid)
)#不适合有外键

查看约束的作用

主键约束


#主键约束 唯一且不为空
INSERT INTO student(sid,sname)
VALUES(NULL,'张三');
INSERT INTO student(sid,sname)
VALUES(1000,'张三');
#二次运行报Duplicate重复

非空约束


#非空约束,不为空但是可以重复
INSERT INTO student(sid,sname)
VALUES(1000,NULL);
INSERT INTO student(sid,sname)
VALUES(1001,'张三');

唯一约束


#唯一约束,不重复但是为空
INSERT INTO student(sid,sname,sphone)
VALUES(1001,'张三',13113131313);
INSERT INTO student(sid,sname,sphone)
VALUES(1003,'王五',NULL);

外键约束


#创建一个成绩表
CREATE TABLE score
(
     scid INT AUTO_INCREMENT PRIMARY KEY,
     ssid INT,
     cid INT,
     grade TINYINT UNSIGNED ,
     FOREIGN KEY(ssid)
     REFERENCES student(sid)#外键
)

#外键作用
INSERT INTO score(ssid,cid,grade)
VALUES(1234,10,98);
#报错,学生表没有1234学号
INSERT INTO score(ssid,cid,grade)
VALUES(1000,10,98);

查看约束名


SHOW CREATE TABLE score;
#结果如下
CREATE TABLE `score` (
  `scid` INT(11) NOT NULL AUTO_INCREMENT,
  `ssid` INT(11) DEFAULT NULL,
  `cid` INT(11) DEFAULT NULL,
  `grade` TINYINT(3) UNSIGNED DEFAULT NULL,
  PRIMARY KEY (`scid`),
  KEY `ssid` (`ssid`),
  CONSTRAINT `score_ibfk_1` FOREIGN KEY (`ssid`) REFERENCES `student` (`sid`)
) ENGINE=INNODB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8

删掉主键约束


ALTER TABLE student DROP PRIMARY KEY;

删除外键


ALTER TABLE score 
DROP FOREIGN KEY score_ibfk_1;
ALTER TABLE student
MODIFY sid INT NULL;

删除非空约束


ALTER TABLE student
MODIFY sname VARCHAR(30) NULL;

删除唯一约束


ALTER TABLE student
DROP INDEX sphone;

建表后增加约束


ALTER TABLE student 
ADD CONSTRAINT PRIMARY KEY(sid);

#给order_status表的id列添加一个外键约束, 
#外键约束的表为employees, 
#对应的列为employee_id;
CREATE TABLE employees
(
      employee_id INT PRIMARY KEY 
)
ALTER TABLE order_status 
ADD CONSTRAINT FOREIGN KEY (id)
REFERENCES employees(employee_id);

VIEW视图

创建视图


#创建视图empvu10
CREATE VIEW empvu10(e_no,e_name,e_job)
AS SELECT empno 工号,ename 姓名,job 职位 FROM 
emp WHERE deptno=10;

#创建视图empvu20
CREATE VIEW empvu20
AS SELECT empno 工号,ename 姓名,job 职位 FROM 
emp WHERE deptno=20;

#创建视图empvu30
CREATE VIEW empvu30(e_no,e_name,e_job)
AS SELECT empno 工号,ename 姓名,job 职位 FROM 
emp WHERE deptno=30;

修改视图


CREATE OR REPLACE VIEW empvu10
AS SELECT empno,ename,job,hiredate FROM 
emp WHERE deptno=10;

#简单视图
#复杂的视图:多表连接,分组,函数


/*
创建视图dept_sum_vu
显示部门名称,部门平均工资,
最高工资,最低工资,工资和
*/
CREATE VIEW dept_sum_vu AS 
SELECT 
d.dname 部门名称,
AVG(e.sal) 平均工资,
MAX(e.sal) 最高工资,
MIN(e.sal) 最低工资 ,
SUM(e.sal) 工资和
FROM emp e, dept d
WHERE e.deptno=d.deptno
GROUP BY d.dname

#简单视图可以操作表数据,如简单增删改查
DELETE FROM empvu10
WHERE ename='clark';

#复杂视图不可以操作表数据
UPDATE dept_sum_vu 
SET 最高工资=8000
WHERE 部门名称='SALES';

删除视图


DROP VIEW empvu20;

#在EMP表上创建一个视图emp_vu20,要求包括RESEARCH部门所有员工的信息
CREATE VIEW emp_vu20 AS 
SELECT * FROM emp 
WHERE deptno=(
SELECT deptno FROM dept
WHERE dname='RESEARCH')

#分别创建两个视图emp_deptview、emp_jobview
#按部门、职位分别统计员工的年薪和.
CREATE OR REPLACE VIEW emp_deptview AS
SELECT deptno,SUM(sal*12)
FROM emp GROUP BY deptno;

CREATE VIEW emp_jobview AS
SELECT job,SUM(sal*12) 年薪和
FROM emp
GROUP BY job;

#通过对视图emp_vu20来更新员工的工资为原来的1.1倍
UPDATE emp_vu20 SET sal=sal*1.1;

#将MySQL默认的结束符修改成$$

#创建一个存储过程名为adddept
#有多个参数n,为传入类型,数据类型是整数
#将MySQL默认的结束符修改成$$
DELIMITER $$
CREATE PROCEDURE adddept(IN n INT)
BEGIN
#声明变量i,类型为int,赋值为1 java int=1
DECLARE i INT DEFAULT 1; 
#循环(重复)n 次 
WHILE  i<=n DO
INSERT INTO dept(dname,loc) 
VALUES(CONCAT('testdept',i),'testlocation');
SET i = i+1;
END WHILE;
END$$
DELIMITER ;
#将结束符修改为默认的分号
DELIMITER ;

#调用存储过程
CALL adddept(1000)

SELECT * FROM dept

#在school数据库中学生表插入1万学生
#要求名字不同,
#学号自增,性别5000个男,5000个女
DESC student

CREATE TABLE student
(
     sid INT AUTO_INCREMENT,
     sname VARCHAR(30) NOT NULL UNIQUE,
     ssex CHAR(1) DEFAULT '男',
     sage TINYINT UNSIGNED
     #check(sage between 18 and 28)
     ,
     sphone CHAR(11) UNIQUE,
     PRIMARY KEY(sid)
)

DELIMITER $$
CREATE PROCEDURE addstu(IN n INT)
BEGIN
DECLARE i INT DEFAULT 1; 
WHILE  i<=n DO
INSERT INTO student(sname,ssex,sage) 
VALUES(CONCAT('张三',i),IF(i<n/2,'男','女'),20);
SET i = i+1;
END WHILE;
END$$
DELIMITER ;

CALL addstu(1000);

TRUNCATE TABLE student 

INDEX索引


解释计划
EXPLAIN SELECT * FROM student WHERE sname='张三1000'

索引的意义

无索引/查询条件未命中索引:MySQL只能“逐行扫描全表”,逐一判断是否符合条件(即全表扫描);有索引且查询条件命中索引:MySQL先通过索引(类似目录)快速定位到目标数据的物理位置,再直接去表中取数据,无需扫描无关记录。

优缺点

索引的核心优点:大幅加速查询(精准/前缀匹配等场景)、减少全表扫描、提升数据检索效率。

索引的核心缺点:占额外存储空间、拖慢增删改(写操作)、可能失效、维护成本高。

创建一个索引


CREATE INDEX student_sname_idx ON 
student(sname);

删除索引


DROP INDEX student_sname_idx ON student;

权限分配


#创建用户
CREATE USER 'test1'@'%' 
IDENTIFIED BY '123456';
/*
@  是 分隔符, %  是 主机匹配通配符,核心含义如下:
 
-  @ :分隔「用户名」和「允许登录的主机」,格式为  '用户名'@'主机名' ,明确该用户能从哪些主机登录MySQL。
-  % :匹配「任意主机」,包括本地服务器、远程电脑等所有网络可达的设备,即  'test1'@'%'  表示  test1  可从任何地方登录。
 
常见主机匹配场景(补充理解):
 
-  'test1'@'localhost' :仅允许从MySQL所在的本地服务器登录(不能远程);
-  'test1'@'192.168.1.100' :仅允许从IP为  192.168.1.100  的特定主机登录;
-  'test1'@'192.168.1.%' :允许从  192.168.1  网段的所有主机登录(通配符%匹配网段后缀)。
*/

#授予全部权限
GRANT ALL PRIVILEGES ON bwf.*TO test1; 
#让权限立即生效
FLUSH PRIVILEGES ;
#修改密码
ALTER USER 'test1'@'%'
IDENTIFIED BY '121212';
#删除用户
DROP USER 'test1'@'%';
© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
none
暂无评论...