qimu666 / MySQL

MySQL复习

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

注意:修正错误:

创建数据库/创建表的表名或字段名为关键字时应该用 `表名/字段名` ,而不是‘表名/字段名’

不建议写法

-- 1. 表名/字段名为关键字时,会自动转为大写
CREATE TABLE NAME(
   DATA DATETIME,
);
-- 2. 用单引号括起来
CREATE TABLE ‘name’(
    ‘data’ DATETIME,
);

推荐使用:

CREATE TABLE `name`(
    `data` DATETIME,
);

1. 创建表

CREATE TABLE emp (
  id INT PRIMARY KEY AUTO_INCREMENT,
  ‘name’ VARCHAR (32),
  sex CHAR (1),
  brithday DATE,
  entry_data DATETIME,
  -- 入职时间
   job VARCHAR (32),
  Salary DOUBLE,
  ‘resume’ TEXT-- 个人介绍
   -- 字符格式  -- 校对规则      --引擎
) CHARSET utf8 COLLATE utf8_bin ENGINE INNODB;

SELECT *FROM emp
         -- 全部字段都要添加字段可以省略emp(表)后()中的字段
INSERT INTO emp VALUES(1,'白骨精','','2001-1-1','2022-2-4 10:32:11','大王',6000,'抓唐僧')

-- 添加数据可以选择字段添加
INSERT INTO emp(id)VALUES(2);

INSERT INTO emp(id,user_name)VALUES(3,'牛魔王');

2. 修改表

# 修改表
-- 员工表emp增加一个image列,varchar类型,要求在‘resume’后面
ALTER TABLE emp 
                         -- 不允许为空 默认值为 ''
       ADD image VARCHAR(32) NOT NULL DEFAULT ''
       -- 在 ‘resume’ 列之后
       AFTER ‘resume’;


ALTER TABLE emp MODIFY job VARCHAR(60);-- 修改列

ALTER TABLE emp DROP sex; -- 删除列

RENAME TABLE emp TO employee;-- 修改表名

SELECT *FROM employee;

INSERT INTO employee(id)VALUES(2);

INSERT INTO employee(id,user_name)VALUES(3,'牛魔王');

DESC employee -- 显示表结构

ALTER TABLE employee CHARSET utf8; -- 修改表的字符集

-- 修改列的名称
-- ALTER TABLE employee CHANGE ‘name’  user_name VARCHAR(64) NOT NULL DEFAULT '';
ALTER TABLE employee CHANGE   
                     ‘name’ -- 要修改的字段(列名)
                      user_name  -- 新的字段(列名)
                      VARCHAR(64);

3. 增删改操作

#增删改语句和注意事项
SELECT *FROM employee;


         -- 全部字段都要添加字段可以省略emp(表)后()中的字段
INSERT INTO employee VALUES(1,'白骨精','','2001-1-1','2022-2-4 10:32:11','大王',6000,'抓唐僧')

-- 添加数据可以选择字段添加
INSERT INTO employee(id)VALUES(2);

INSERT INTO employee(id,user_name)VALUES(3,'牛魔王');

-- ——————————————————————————————————————————————————————————

-- 将所有员工的工资修改为5000,如果没有带where条件会修改所有的记录 【慎用】
UPDATE employee SET Salary =5000;
-- 将姓名为牛魔王 的工资修改为3000块 where子句指定应更新哪些行,没有则更新所有的行
UPDATE employee SET Salary =3000 WHERE user_name='牛魔王' ;
-- 给白骨精涨1000块钱工资
UPDATE employee SET Salary =Salary+1000 WHERE user_name='白骨精' ;
-- 修改多个字段(列)的值,可以通过SET 字段1=值1,字段2=值2...
UPDATE employee SET Salary =3000,job='火焰山大王' WHERE user_name='牛魔王' ;

-- ——————————————————————————————————————————————————————————

-- 删除表中id为2的记录
DELETE FROM employee WHERE id =2;

-- 删除表
DROP TABLE employee;

4. 查询操作

4.1 查询01

#select查询

 CREATE TABLE student (
  id INT NOT NULL DEFAULT 1,
  NAME VARCHAR (20) NOT NULL DEFAULT '',
  chinese FLOAT NOT NULL DEFAULT 0.0,
  english FLOAT NOT NULL DEFAULT 0.0,
  math FLOAT NOT NULL DEFAULT 0.0
);

INSERT INTO student(id,NAME,chinese,english,math)VALUES(1,'韩函',89,78,90);
INSERT INTO student(id,NAME,chinese,english,math)VALUES(2,'张飞',67,98,56);
INSERT INTO student(id,NAME,chinese,english,math)VALUES(3,'米江',87,78,77);
INSERT INTO student(id,NAME,chinese,english,math)VALUES(4,'关羽',88,98,90);
INSERT INTO student(id,NAME,chinese,english,math)VALUES(5,'赵云',82,84,67);
INSERT INTO student(id,NAME,chinese,english,math)VALUES(6,'欧阳锋',55,85,15);
INSERT INTO student(id,NAME,chinese,english,math)VALUES(7,'黄蓉',75,65,30);

-- 查询所有学生信息
SELECT * FROM student;
-- 查询表中所有学生的姓名和对应的英语成绩
SELECT NAME,english FROM student;
-- 过滤表中重复的数据  每个字段都相同,才会去重
SELECT DISTINCT * FROM student;-- 没有重复不过滤
SELECT DISTINCT english FROM student;-- 过滤英语成绩相同的记录 可以去重
SELECT DISTINCT NAME , english FROM student;-- 过滤英语成绩相同的记录,每个字段都相同,才会去重

-- 统计每个学生的总分
SELECT NAME,(chinese+english+math) FROM student;
-- 给每个学生加10分
SELECT NAME,(chinese+english+math+10) FROM student;
-- 使用别名查询分数 AS
SELECT NAME AS '姓名',(chinese+english+math) AS '总分' FROM student;

# where ——————————————————————————————————————————————————————————————————————————————————————————————————

-- 查询math大于60并且id大于3的学生成绩
SELECT * FROM student WHERE math > 60 AND id > 3;
-- 查询英语成绩大于语文成绩的同学
SELECT * FROM student WHERE english > chinese;
-- 查询总分大于200,并且数学大于语文成绩的,姓韩的同学
-- 韩%  表示 名字以韩开头就可以 ,0-n个,只要开头是韩就可以
SELECT * FROM student                                                               
                      WHERE (chinese+english+math) > 200 
                      AND math > chinese AND NAME LIKE '韩%';                   
-- 查询英语分数在80-90之间的同学
SELECT * FROM student WHERE english >= 80 AND english <= 90;      
SELECT * FROM student WHERE english BETWEEN 80 AND 90; --  BETWEEN...and ..是闭区间包含两头         
-- 查询数学分数为89,90,77的同学
SELECT * FROM student WHERE math = 89 OR math = 90 OR math = 77; 
SELECT * FROM student WHERE math IN (89,90,77);                                        
-- 查询所有姓赵的同学成绩
SELECT * FROM student WHERE NAME LIKE '赵%';
-- 查询数学比语文多1分的同学
SELECT * FROM student WHERE (math - chinese) =1;

# order by 排序 ——————————————————————————————————————————————————————————————————————————————————————————————————

-- 对数学成绩排序后输出【升序】
-- ASC升序[默认]
SELECT math FROM student ORDER BY math ASC;
-- 对总分按照从高到低的顺序输出
-- DESC降序 
SELECT NAME,(chinese+english+math) AS '总分' FROM student ORDER BY 总分 DESC;

# count() 统计 ——————————————————————————————————————————————————————————————————————————————————————————————————
-- count:返回行的总数

-- 统计一个班级有多少学生
SELECT COUNT(*) AS '总人数' FROM student;
-- 统计数学成绩大于60的学生有多少个
SELECT COUNT(*) AS '数学成绩大于90分' FROM student WHERE math > 60 ;
-- 统计总分大于250的人有多少
SELECT COUNT(*) AS '总分大于250分' FROM student WHERE (chinese+english+math) > 250 ;

-- count(*) 和 count(列的区别)
-- 解释: count(*) 返回满足条件的记录行数
--        count(列) 统计满足条件的某列非空的有多少个,但会排除数据为null的数据

CREATE TABLE count_test (
              ‘name’ VARCHAR(20));
              
INSERT INTO count_test VALUES('jake');
INSERT INTO count_test VALUES('qimu');
INSERT INTO count_test VALUES('marry');
INSERT INTO count_test VALUES(NULL);

SELECT * FROM count_test;
-- count(*)  返回满足条件的记录行数
SELECT COUNT(*) FROM count_test;
-- count(列) 统计满足条件的某列非空的有多少个,但会排除数据为null的数据
SELECT COUNT(‘name’) FROM count_test;


-- sum 求和——————————————————————————————————————————————————————————————————————————————————————————————————
-- 注意:仅对数值有效,否则会报错
--       对于多列求和, , (逗号)不能少

-- 统计一个班级的数学总成绩
SELECT SUM(math) FROM student;
-- 统计一个班的语文,英语,数学各科的总成绩
SELECT SUM(chinese),SUM(english),SUM(math) FROM student;
-- 统计一个班的语文,英语,数学的成绩总和;
SELECT SUM(chinese+english+math) AS '成绩总和' FROM student;
-- 统计一个班的语文成绩平均分
SELECT SUM(chinese)/COUNT(*) FROM student;

-- avg 求平均值——————————————————————————————————————————————————————————————————————————————————————————————————
 
-- 求一个班级数学的平均分
SELECT AVG(math) FROM student;
-- 求一个班级总分的平均分
SELECT AVG(chinese+english+math) FROM student;

-- min/max 最小值/最大值

-- 求班级最高分和最低分
SELECT
  MAX(chinese + english + math) AS '最高分',
  MIN(chinese + english + math) AS '最低分'
FROM
  student;
-- 求班级数学最高分和最低分
SELECT MAX(math) AS '数学最高分',
       MIN(math) AS '数学最低分' FROM student;

4.2 查询02

-- 部门表
CREATE TABLE dept( 
deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
dname VARCHAR(20) NOT NULL DEFAULT "",
loc VARCHAR(13)NOT NULL DEFAULT ""
);

INSERT INTO dept VALUES (10,'ACCOUNTING','NEW YORK'),
                        (20,'RESEARCH','DALLAS'),
                        (30,'SALES','CHICAGO'),
                        (40,'OPERATIONS','BOSTON');
SELECT * FROM dept;

-- 员工表
CREATE TABLE emp(
empno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, -- 编号
ename VARCHAR(20) NOT NULL DEFAULT "", -- 名字
job VARCHAR(9) NOT NULL DEFAULT "", -- 工作
mgr MEDIUMINT UNSIGNED, -- 上级编号
hiredate DATE NOT NULL , -- 入职时间
sal DECIMAL(7,2) NOT NULL,-- 薪水
comn DECIMAL(7,2),-- 奖金
deptno  MEDIUMINT UNSIGNED NOT NULL DEFAULT 0 -- 部门编号
);

INSERT INTO emp VALUES(7369,'SMITH','CLERK',7902,'1990-12-17',800.00,NULL,20),
(7499,'ALLEN','SALESMAN',7698,'1991-2-20',1600.00,300.00,30),
(7521,'WARD','SALESMAN',7698,'1991-2-22',1250.00,500.00,30),
(7566,'JONES','MANAGER',7839,'1991-4-2',2975.00,NULL,20),
(7654,'MARTIN','SALESMAN',7698,'1991-9-28',1250.00,1400.00,30),
(7698,'BLAKE','MANAGER',7839,'1991-5-1',2850.00,NULL,30),
(7782,'CLARK','MANAGER',7839,'1991-6-9',2450.00,NULL,10),
(7788,'SCOTT','ANALYST',7566,'1997-4-19',3000.00,NULL,20),
(7839,'KING','PRESIDENT',NULL,'1991-11-17',5000.00,NULL,10),
(7844,'TURNER','SALESMAN',7698,'1991-9-8',1500.00,NULL,30),
(7900,'JAMES','CLERK',7698,'1991-12-3',950.00,NULL,30),
(7902,'FoRD','ANALYST',7566,'1991-12-3',3000.00,NULL,20),
(7934,'MILLER','CLERK',7782,'1992-1-23',1300.00,NULL,10);

SELECT * FROM emp;

-- 工资级别表
CREATE TABLE salgrade( 
grade MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,-- 工资级别
losal DECIMAL (17,2) NOT NULL,    -- 该级别最低工资
hisal DECIMAL(17,2)NOT NULL       -- 该级别最高工资
);
INSERT INTO salgrade VALUES (1,700,1200);
INSERT INTO salgrade VALUES (2,1201,1400);
INSERT INTO salgrade VALUES (3,1401,2000);
INSERT INTO salgrade VALUES (4,2001,3000);
INSERT INTO salgrade VALUES (5,3001,9999);

-- 查询表
SELECT * FROM dept;
SELECT * FROM emp;
SELECT * FROM salgrade;

# group by + having ——————————————————————————————————————————————————————————————————————————————————

-- 如何显示每个部门的平均工资和最高工资
SELECT AVG(sal) ,MAX(sal),deptno FROM emp GROUP BY deptno;

-- 显示每个部门的每种岗位的平均工资和最低工资
SELECT AVG(sal) ,MIN(sal),deptno,job FROM emp GROUP BY deptno ,job;

-- 显示平均工资低2000的部门号和它的平均工资/别名
SELECT AVG(sal) AS sal_avg, deptno FROM emp GROUP BY deptno HAVING sal_avg<2000;

4.3 查询增强

SELECT * FROM dept;
SELECT * FROM emp;
SELECT * FROM salgrade;

-- 使用where子句————————————————————————————————————————————————————————————————————————————————————————————————
-- ?如何查找1992.1.1后入职的员工
-- 说明:在mysq1中,日期类型可以直接比较 ,要注意格式
SELECT * FROM emp WHERE hiredate > '1992-01-01';

-- 使用1ike操作符(模糊)
-- % (百分号): 表示0到多个任意字符 , _ (下划线):表示单个任意字符
-- 如何显示首字符为S的员工姓名和工资
SELECT ename,sal FROM emp WHERE ename LIKE 'S%';

-- ?如何显示第三个字符为大写0的所有员工的姓名和工资
SELECT ename,sal FROM emp WHERE ename LIKE '__O%';

-- 如何显示没有上级的雇员的情况
SELECT * FROM emp WHERE mgr IS NULL;

-- 查询表结结构
DESC emp;

-- 使用order by子句——————————————————————————————————————————————————————————————————————————————————————
-- ?如何按照工资的从低到高的顺序[升序],显示雇员的信息
SELECT * FROM emp ORDER BY sal;

-- ?按照部门号升序而雇员的工资降序排列,显示雇员信息
SELECT * FROM emp ORDER BY deptno ,sal DESC;

# 分页查询 ————————————————————————————————————————————————————————————————————————————————————————————
-- 按雇员的id号升序取出,每页显示3条记录,请分别显示第1页,第2页,第3页
-- 第一页
SELECT * FROM emp ORDER BY empno LIMIT 0 ,3;
-- 第二页
SELECT * FROM emp ORDER BY empno LIMIT 3 ,3;
-- 第三页
SELECT * FROM emp ORDER BY empno LIMIT 6 ,3;

-- groub by ——————————————————————————————————————————————————————————————————————————————————————————————————
-- (1)显示每种岗位的雇员总数、平均工资。
SELECT COUNT(*),AVG(sal),job FROM emp GROUP BY job;

-- (2)显示雇员总数,以及获得补助的雇员数。
SELECT COUNT(*),COUNT(comn)FROM emp;

-- 统计没有获得补助的雇员数
SELECT COUNT(*),COUNT(IF(comn IS NULL,1,NULL)) FROM emp;
SELECT COUNT(*),COUNT(*)-COUNT(comn) FROM emp;

-- (3)显示管理者的总人数。-- DISTINCT 去重复
SELECT COUNT(DISTINCT mgr)FROM emp;

-- (4)显示雇员工资的最人差额。
SELECT MAX(sal)-MIN(sal) FROM emp;

-- ————————————————————————————————————————————————————————————————————————————————————————————————————————————————
-- 如果 select 语句同时包含有 group by,having,limit,order by 
-- 那么他们的顺序是 group by,having,order by,limit

-- 应用案例:请统计各个部门的平均工资,并且是大于1000的,
-- 并且按照平均工资从高到纸排序,取出前两行记录.
SELECT AVG(sal) AS avg_sal,deptno FROM emp GROUP BY deptno
                                  HAVING avg_sal>1000
                                  ORDER BY avg_sal DESC 
                                  LIMIT 0,2 ;
 

5. 多表查询

5.1 笛卡尔集

多表查询的条件不能少于表的个数-1,否则会出现笛卡尔集

-- 多表查询的笛卡尔集
-- 这样会出现笛卡尔集
SELECT * FROM emp , dept;

-- 显示雇员名,雇员工资,部门号及所在部门的名字
                        -- 当我们需要指定显示某个表的列时,指要表名.列名
SELECT ename ,sal, dname , emp.deptno 
                   FROM emp , dept 
                -- 多表查询的条件不能少于表的个数-1,否则会出现笛卡尔集
                   WHERE emp.deptno = dept.deptno;

-- 如何显示部门号为10的部门名、员工名和工资
SELECT ename,sal,dname ,emp.deptno FROM emp,dept
                       WHERE emp.deptno = dept.deptno
                       AND emp.deptno=10;
                       
 -- 显示各个员工的姓名,工资,及其工资的级别
 SELECT ename ,sal ,grade FROM emp, salgrade
                          WHERE sal BETWEEN losal AND hisal ;

-- 练习:显示雇员名,雇员工资及所在部门的名字,并按部门排序降序排.
SELECT ename ,sal ,dname,emp.deptno 
                   FROM emp , dept
                   WHERE emp.deptno = dept.deptno
                   ORDER BY emp.deptno DESC;

5.2 自连接

自连接特点 :

  1. 把同一张表当做两张表使用
  2. 需要给表取别名表名表别名
  3. 列名不明确,可以指定列的别名列名as列的别名
-- 多表查询的自连接

-- 显示公司员工名字和他的上级的名字

/* 分析:
         员工名字在emp表,上级的名字的名字也在emp表
         员工和上级是通过emp表的mgr和empno列关联
*/

-- 自连接特点:
--             1.把同一张表当做两张表使用
--             2.需要给表取别名表名表别名
--             3.列名不明确,可以指定列的别名列名as列的别名

-- 用笛卡尔集的方式查询
SELECT worker.ename AS '员工',boss.ename AS '上级' 
                    FROM emp worker, emp boss
                    WHERE worker.empno = boss.mgr;

5.3 子查询

子查询是指嵌入在其它sql语句中的selecti语句,也叫嵌套查询

5.3.1 单行子查询

单行子查询是指只返回一行数据的子查询语句

-- 如何显示与SMITH同一部门的所有员工?
/*
   1.先查询到SMITH的部门号
   2.把查询到SMITH的部门号的sql语句当做一个子查询来使用
*/
SELECT deptno FROM emp
          WHERE ename = 'SMITH';
          
SELECT * FROM emp 
         WHERE deptno =(
-- 把查询到SMITH的部门号的sql语句当做一个子查询来使用         
		SELECT deptno 
		FROM emp
		WHERE ename = 'SMITH'
          );
          
5.3.2 多行子查询

多行子查询指返回多行数据的子查询 便用关键子 in

-- 课堂练习:如何查询和部门10的工作相同的雇员的
-- 名字、岗位、工资、部门号,但是不含10号部门自已的雇员. 

-- 1.先查询到部门号为10的雇员有哪些工作
SELECT DISTINCT job FROM emp 
         WHERE deptno =10;   

-- 2.
SELECT ename,job,sal,deptno FROM emp 
             WHERE job IN(
                      SELECT DISTINCT job 
                      FROM emp 
                      WHERE deptno =10
              ) AND deptno != 10;       

6. 常用函数

6.1 字符串函数

# 字符串相关函数
-- CHARSET(str) 返回字串字符集
SELECT CHARSET(ename) FROM emp;

-- CONCAT() 连接字串,将多个列拼接成一列
SELECT CONCAT(ename,' 工作是 ' , job ,' a') FROM emp;

-- INSERT(string,substring) 返回substring在string中出现的位置,没有返回0
-- dual 亚元表 ,系统表 可以作为测试表使用
SELECT INSERT('aaaaqimu666', 'q') FROM DUAL;

-- UCASE() 转换大写
SELECT UCASE(ename) FROM emp;

-- LCASE() 转换小
SELECT LCASE(ename) FROM emp;

-- LEFT(str,length),从str中的左边起取length个字符
SELECT LEFT(ename,2) FROM emp;

-- RIGHT(str,length),从str中的右边起取length个字符
SELECT RIGHT(ename,2) FROM emp;

-- LENGTH(str) string长度[按照字节]
SELECT LENGTH(ename) FROM emp;
SELECT LENGTH('柒木') FROM emp;

-- REPLACE(str , search_str , replace_str )
-- 在str中用 replace_str 替换 search_str
-- 例:如果在job中查询到 MANAGER , 就替换成经理
SELECT ename ,REPLACE(job , 'MANAGER' , '经理') FROM emp ;

-- STRCMP(str1,str2)  逐字符比较两字串大小
-- 返回 1 str1 大 ,0 相等 ,-1 str2 大
SELECT STRCMP('qimu1','QIMU') FROM DUAL;

-- SUBSTRING(str , position[ , length ])
-- 从str 的 position开始【从1开始计算】,截取length个字符
-- 从ename字段的数据第一个位置开始截取4个字符,
-- [注意] position 不能为0
SELECT SUBSTRING(ename,1,4) FROM emp;
 
-- LTRIM(str) 去除前端空格
-- RTRIM(str) 去除后端空格
-- TRIM(str)  去除前后两端空格
SELECT LTRIM(' 223的观点') FROM DUAL;
SELECT RTRIM('223的观点  ') FROM DUAL;
SELECT TRIM(' 223的观点  ') FROM DUAL;


#  练习:以首字母小写的方式显示所有员工emp表的姓名 (2种)
-- 1.
SELECT CONCAT(LCASE(SUBSTRING(ename,1,1)),SUBSTRING(ename,2)) AS '姓名'FROM emp  ;
-- 2.
SELECT CONCAT(LCASE(LEFT(ename,1)),SUBSTRING(ename,2)) AS '姓名'FROM emp  ;

SELECT * FROM emp;

6.2 数学函数

# 数学函数——————————————————————————————————————————————————————————

-- ABS(num) 绝对值
-- dual 亚元表
SELECT ABS(10) FROM DUAL;

-- BIN(decimal_number) 十进制转二进制
SELECT BIN(10) FROM DUAL;

-- CEILING(num) 向上取整 ,得到比num 大的最小整数
SELECT CEILING(1.1) FROM DUAL; 

-- FLOOR(num) 向下取整 ,得到比num 小的最大整数
SELECT FLOOR(1.1) FROM DUAL; 

-- CONV(num , from_base , to_base) 进制转换
-- 下面的含义是:8 是十进制的8,转为2进制
SELECT CONV(8,10,2) FROM DUAL;

-- FORMAT(num ,decimal_places) 保留小数位数(四舍五入)
-- 保存小数点2位
SELECT FORMAT(1.345211,2) FROM DUAL; 

-- LEAST( num1,num2[, ....] )  求多个里面的最小值
SELECT LEAST(11,-1,-9,8) FROM DUAL; 

-- MOD (num , denominator )   求余
SELECT MOD(10,3) FROM DUAL; 

-- RAND([seed])  返回随机数 范围 0 <= v <= 1.0;
-- 如果使用 RAND() 每次执行返回不同的随机数, 范围 0 <= v <= 1.0;
SELECT RAND() FROM DUAL; 
--  如果使用 RAND(seed) 返回不同的随机数, 范围 0 <= v <= 1.0 ,如果seed不变则随机数也不会改变
SELECT RAND(1) FROM DUAL; 
SELECT RAND(3) FROM DUAL; 

6.3 时间和日期函数

#日期时间相关函数

-- CURRENT_DATE()  当前日期
SELECT CURRENT_DATE() FROM DUAL; 

-- CURRENT_TIME()  当前时间
SELECT CURRENT_TIME() FROM DUAL; 

-- CURRENT_TIMESTAMP() 当前时间戳
SELECT CURRENT_TIMESTAMP() FROM DUAL; 

-- NOW()  当前的日期和时间
SELECT NOW() FROM DUAL;

-- YEAR | MONTH | DAY | DATE(datetime) 返回指定的年或月或日
SELECT YEAR(NOW()) FROM DUAL;
SELECT MONTH(NOW()) FROM DUAL;
SELECT YEAR('2022-9-9') FROM DUAL;

-- DATE_ADD ( date, INTERVAL d_value d_type)  中date中加上日期或时间
-- INTERVAL后面可以是year minute second hour day等
-- 请查询在10分钟内发布的新闻
SELECT * FROM mes WHERE DATE_ADD(send_time, INTERVAL 10 MINUTE)>=NOW();

-- DATE_SUB( date, INTERVAL d_value d_type)  中date中减去日期或时间
-- 请查询在10分钟内发布的新闻
SELECT * FROM mes WHERE send_time >= DATE_SUB(NOW(), INTERVAL 10 MINUTE);

-- DATEDIFF(date1,date2) 两个日期差(结果是天)
SELECT DATEDIFF('2011-11-11','1990-01-01') FROM DUAL

-- UNIX_TIMESTAMP() 返回1970-1-1 到现在的秒数
SELECT UNIX_TIMESTAMP() FROM DUAL;

-- FROM_UNIXTIME() 可以把 UNIX_TIMESTAMP 秒数【时间戳】,转成指定格式的日期
-- %Y-%m-%d 表示年月日
-- %Y-%m-%d %H:%i:%s 表示年月日时分秒
SELECT FROM_UNIXTIME(1662645690,'%Y-%m-%d') FROM DUAL;
SELECT FROM_UNIXTIME(1662645690,'%Y-%m-%d %H:%i:%s') FROM DUAL;


-- 创建测试表 信息表
CREATE TABLE mes(
id INT,
content VARCHAR(30),
send_time DATETIME
);

-- 添加一条记录   使用时间戳
INSERT INTO mes VALUES(1,'北京新闻',CURRENT_TIMESTAMP());
--                使用 NOW() 函数
INSERT INTO mes VALUES(2,'广州新闻',NOW());
--                普通方法
INSERT INTO mes VALUES(3,'上海新闻','2022-9-19');

INSERT INTO mes VALUES(4,'河南新闻',CURRENT_TIMESTAMP());


#  应用实例:
-- 1.显示所有新闻信息,发布日期只显示日期,不用显示时间
SELECT id,content,DATE(send_time) FROM mes;

-- 2.请查询在10分钟内发布的新闻
-- (1).
SELECT * FROM mes WHERE DATE_ADD(send_time, INTERVAL 10 MINUTE)>=NOW();
-- (2).
SELECT * FROM mes WHERE send_time >= DATE_SUB(NOW(), INTERVAL 10 MINUTE);

-- 3.请在mysq1的sq1语句中求2011-11-11和1990-1-1相差多少天
SELECT DATEDIFF('2011-11-11','1990-01-01') FROM DUAL

-- 4.请用mysq1的sg1语句求出你活了多少天?
SELECT DATEDIFF(NOW(),'2002-05-14') FROM DUAL;

-- 5.如果你能活80岁,求出你还能活多少天
SELECT DATEDIFF(DATE_ADD('2002-05-14', INTERVAL 80 YEAR),NOW()) FROM DUAL;

SELECT * FROM mes

6.4 加密和系统函数

-- USER() 查询用户
-- 可以查看登录到mysq1的有哪些用户,以及登录的ip
SELECT USER() FROM DUAL; -- 用户@ip地址

-- DATABASE(); 查询当前使用数据库名称
SELECT DATABASE();

-- MD5(str) 为字符串算出一个MD5 32位的字符串,常用(用户密码)加密
-- root密码是 qimu ->加密md5->在数据库中存放的是加密后的密码
SELECT MD5('qimu')FROM DUAL;

-- 演示用户表 ,存放密码 是MD5
CREATE TABLE user_md5 (
  `ame` VARCHAR (20) NOT NULL DEFAULT '',
  pwd CHAR (32) NOT NULL DEFAULT ''
);

INSERT INTO user_md5 VALUES ('柒木',MD5('qimu'));

-- 查询 的时候要加上MD5() 才能查到
SELECT * FROM user_md5 WHERE ame = '柒木' AND pwd =MD5('qimu');

SELECT * FROM user_md5;

-- PASSWORD(str) 加密函数  MySQL数据库的用户密码就是用PASSWORD函数加密
SELECT PASSWORD('qimu')FROM DUAL;

6.5 控制流程函数

-- IF(expr1,expr2,expr3) 如果expr1为True,则返回expr2,否则返回expr3
SELECT IF(TRUE,'上海','北京') FROM DUAL;

-- IFNULL(expr1,expr2) 如果expr1不为空NULL,则返回expr1,否则返回expr2
SELECT IFNULL(NULL,'柒木') FROM DUAL;

-- SELECT CASE WHEN expr1(TRUE/FALSE) THEN expr2 
            -- WHEN expr3(TRUE/FALSE) THEN expr4 
            -- ..... 
            -- ELSE expr5 END;[类似多重分支]
            
-- 如果 expr1 为TRUE 则返回expr2,
-- 如果 expr1 为FALSE , expr3 为TRUE 则返回expr4,
-- 如果 如果 expr1 为FALSE , expr3 为FALSE 则返回expr5,

SELECT CASE WHEN TRUE THEN 'jake' 
            WHEN TRUE THEN 'tom' 
            ELSE 'mary' END;
            
-- 查询emp表,如果comm是null,则显示0.0
-- 判断是否为nul1要使用is nul1,判断不为空使用is not  
 SELECT ename ,IF(comn IS NULL,0.0,comn) FROM emp;          
 
 SELECT ename ,IFNULL(comn ,0.0) FROM emp;          
 
-- 如果emp表的job是 CLERK 则显示职员,
-- 如果是MANAGER则显示经理
-- 如果是SALESMAN则显示销售人员,其它正常显示
SELECT ename ,(SELECT CASE 
            WHEN job = 'CLERK' THEN '职员'
            WHEN job = 'MANGER'THEN '经理'
            WHEN job = 'SALESMAN' THEN '销售人员'
            ELSE job END) AS 'job'
            FROM emp;

7. 临时表

1. 创建测试表

CREATE TABLE goods(
goods_id INT,
cat_id INT,
goods_sn VARCHAR(10),
goods_name VARCHAR(60),
goods_price DOUBLE,
goods_model INT,
goods_weight VARCHAR(20)
);

2. 添加数据

由于要测试的数据比较多,这边使用IDEA来添加数据

2.1 通过IDEA快速添加数据
  1. 导入Druid,dbutils ,mysql 三个jar包 ,

image

  1. 选中三个jar包右键添加到项目中

image

image

  1. 在src目录下创建druid.properties文件
driverClassName=com.mysql.jdbc.Driver
# 数据库地址
url=jdbc:mysql://localhost:3306/fuxi?characterEncoding=UTF-8&rewriteBatchedStatements=true
username=数据库账号
password=数据库密码

#\u521D\u59CB\u5316\u8FDE\u63A5\u6570
initialPoolSize=10
#\u6700\u5C0F\u8FDE\u63A5\u6570
minIdle=5
#\u6700\u5927\u8FDE\u63A5
maxActive=50
# \u8D85\u65F6\u65F6\u95F4\uFF0C\u4EE5\u6BEB\u79D2\u4E3A\u5355\u4F4D\uFF0C1000\u6BEB\u79D2==1\u79D2
maxWait=5000
  1. 创建JDBCDruid工具类 ,可以频繁使用
import com.alibaba.druid.pool.DruidDataSourceFactory;


import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;

import java.sql.Statement;
import java.util.Properties;

public class JDBCDruid {
    private static DataSource ds;

    static {
        try {
            Properties properties = new Properties();
            properties.load(new FileInputStream("D:\\学习\\qimu\\src\\druid.properties"));
            ds = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static Connection getConnection() throws Exception {
        return ds.getConnection();
    }

    public static void close(ResultSet resultSet, Statement statement, Connection connection) {
        try {
            if (resultSet != null) {
                resultSet.close();
            }
            if (statement != null) {
                statement.close();
            }
            if (connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}
  1. 创建Test类用于提交sql语句
import org.apache.commons.dbutils.QueryRunner;

import java.sql.Connection;


public class Test {
    public static void main(String[] args) throws Exception {
        Connection connection = JDBCDruid.getConnection();
        QueryRunner queryRunner = new QueryRunner();
        String sql = "INSERT INTO goods VALUES(?,?,?,?,?,?,?)";
        int update = 0;
        for (int i = 0; i < 20; i++) {
            int a = (int) (Math.random() * 10+1);
            double b = (int) (Math.random() * 3000+2000);
            update = queryRunner.update(connection, sql, i,a,"ECS00000"+i,a+a+"手机"+a,b,a+a+a+i+a,a+a+"KG");
        }
        System.out.println(update > 0 ? "执行成功" : "执行失败");
        JDBCDruid.close(null, null, connection);
    }
}

3. 执行SQL查询语句

查询goods表中各个类别中,价格最高的商品 , 并且对商品进行升序排列

-- 1.查询到每个商品类别的最高价
SELECT cat_id,MAX(goods_price) FROM goods GROUP BY cat_id;
-- 2.用goods表与临时表进行查询
-- goods.cat_id 表示:两个表中都有的字段要表明查询的是哪个表中的字段,不能直接写
SELECT goods_id,goods.cat_id,goods_name,goods_price 
         FROM goods ,(
              --  把第一步的sql语句当作一个临时表 与 goods 表进行查询     
                      SELECT cat_id,MAX(goods_price) AS max_price
                      FROM goods 
                      GROUP BY cat_id
                      ) temp
           --  临时表temp 的cat_id要等于 goods表的 cat_id
           --  并且临时表temp的最高价格max_price要等于goods中的商品价格goods_price
         WHERE goods.cat_id = temp.cat_id
         AND   goods.goods_price = temp.max_price
         -- 对cat_id进行升序排列
         ORDER BY temp.cat_id;

-- 所有数据 
SELECT * FROM goods;
-- 删除表
DROP TABLE goods;

About

MySQL复习