java第一阶段(day14)MySQL

本文深入探讨了MySQL数据库管理系统,包括其安装、基本指令、数据类型、约束、DML操作、DQL查询以及数据库设计。通过实例展示了如何创建数据库、表,以及进行数据的插入、更新和删除操作。此外,还讲解了如何使用各种条件查询、分组查询和子查询,以及数据库的备份与恢复。最后,提到了数据库的存储引擎和数据持久化的重要性。

1.DBMS

为什么学习io?
  数据持久化。  io不太好用。逻辑操作比较复杂。
  
换另外一种技术实现数据的持久化?
     将数据存储到库里面----->数据库  Database
     
听说过的数据库:  Mysql  oracle  sqlserver sqllite
               Mogodb  redis Elastic
              
存储不同数据类型的数据。

数据库的分类:
   1.从存储位置分析:
      基于磁盘: Mysql Oracle Sqlserver  肯定可以保证数据持久化。IO 性能低
      基于缓存: Redis Mysql  数据不能够完全的保证持久化  快 
      
   2.从关系划分:
      关系型数据库: Mysql Oracle Sqlserver    字段与字段表直接都是有关系的
      非关系型数据库: Redis  NOSQL  NOT ONLY SQL 
           key:value

为什么要学习数据库?
    数据持久化.

DBMS:
   database management system  数据库管理系统。
   Mysql: 就是一个软件, 是一个数据库管理系统软件。 RDBMS. 

数据库管理系统(Database Management System)是一种操纵和管理数据库的大型软件,用于建立、使用和维护数据库,简称DBMS。它对数据库进行统一的管理和控制,以保证数据库的安全性和完整性。用户通过DBMS访问数据库中的数据,数据库管理员也通过DBMS进行数据库的维护工作

2. MySQL

2.1 安装mysql的服务

下载安装Mysql的服务端程序。MySQL :: Download MySQL Installer

mysql服务端程序的端口号:  3306
mysql的协议:  TCP/IP   客户端连接服务器  保证服务器是开启的。

mysql的用户名都是:  root
mysql的密码都是自定义: root

mysql的核心配置文件:  C:\ProgramData\MySQL\MySQL Server 5.7\my.ini

max_connections=151
tomcat: 200

2.2 客户端连接服务器

客户端要连接哪一台主机的mysql的服务器?
    ip  3306 用户名  密码

配置mysql的环境变量。

所有的指令+sql语句都是不区分大小写。 每一行的结束必须带 ;

-- 连接mysql指令
-- mysql -hip地址  -u用户名 -p
-- C:\Users\JAVASM>mysql -h 127.0.0.1 -uroot -p
-- C:\Users\JAVASM>mysql -h localhost -uroot -p

-- 如果是连接本机的服务  -hip可以省略的
C:\Users\JAVASM>mysql -uroot -p

2.3 mysql基本指令

mysql软件里面都有啥?
  有很多数据库:  db
  db的组成部分:
      1. table 表
          1.1 字段(属性) 列
          1.2 数据类型
          1.3 约束
          
      2. 查询
      3. 函数
      5. 索引
      6. 存储过程
      7. 触发器
      8. 备份

-- mysql> show databases;  查看所有的数据库

mysql> select database(); -- 查看当前正在使用的数据库
+------------+
| database() |
+------------+
| NULL       |
+------------+

mysql> use mysql;-- 选择使用的数据库
Database changed

mysql> select database();
+------------+
| database() |
+------------+
| mysql      |
+------------+

mysql> show tables; -- 查看指定库里面所有的表

mysql> desc user; -- 查看指定表的表结构

mysql> select * from user; -- 查看表里面所有的记录  *:通配符 表里面所有的字段

mysql> select host, User from user; -- 指定列查询 查询部分字段

3. SQL

使用sql操作数据库的表。 SQL: structured query language  结构查询语言

-- 1. DDL data definitation language 数据定义语言
       创建库 创建表  删除库  删除表  create /drop/ truncate
-- 2. DML 数据操作语言(更新操作)
      insert  update  delete

-- 3. DQL 数据查询语言  select

-- 4. DCL 数据控制语言   事务   权限

3.1  DDL

1. 操作库

mysql> create database mydb ; -- 创建数据库  数据库名称一旦定义  无法修改
Query OK, 1 row affected (0.00 sec)

mysql> drop database mydb; -- 删除数据库(连着库里面的表都全部删除  数据无法回滚的)


mysql> show create database mydb;-- 展示创建数据库的相关的信息
+----------+-----------------------------------------------------------------+
| Database | Create Database                                                 |
+----------+-----------------------------------------------------------------+
| mydb     | CREATE DATABASE `mydb` /*!40100 DEFAULT CHARACTER SET latin1 */ |
+----------+-----------------------------------------------------------------+

2.操作表

-- 创建表格(数据 列(字段)  数据类型  约束)
create table 表名(
   列名1 数据类型  [约束],
   列名2 数据类型  [约束],
   .....
   列名n 数据类型  [约束]

);


-- 需求: 创建表 存储所有的用户信息
create table userinfo(
  id int,
  username varchar(20),
  gender char(1),
  phone char(11),
  age tinyint(2) unsigned,
  balance decimal(15,4),
  password varchar(70),
  birthday date,
  create_time datetime,
  update_time datetime,
  last_login_time datetime  
);

映射关系:
   代码操作数据。
   一张表就是一个类。
   表里面的字段就是类里面属性,
   表里面字段的数据类型 就是类里面属性的数据类型。

操作表结构:  alter(了解)

mysql> drop table a;  -- 删除表 (数据无法回滚)
Query OK, 0 rows affected (0.14 sec)

mysql> alter table userinfo add address varchar(30);
-- 新增新的列

mysql> alter table userinfo drop address;  -- 删除指定的列

-- 可以修改列名  也可以修改类的数据类型
mysql> alter table userinfo change username username varchar(25);
mysql> alter table userinfo change username name varchar(25);

-- 修改列的数据类型
mysql> alter table userinfo modify name varchar(20);

-- 修改指定的表的名称
mysql> alter table userinfo rename tb_userinfo;
Query OK, 0 rows affected (0.10 sec)

3.2. 数据类型

java数据类型:  引用+基本      基本: 4类8种

  • 整数类型  byte short  int  long
  • 小数类型 float  double
  • 布尔类型 boolean
  • 字符类型 char

1 整数类型

-- 1. tinyint(n) 类似byte -128-127  人的年龄  unsigned  0-255
      tinyint(1) 类似boolean   0false   1true
      
-- 2. int(n)  类似int  id
-- 3. bigint(n) 类似long  id  时间的毫秒数

n: 限定列宽的宽度。 
-- unsigned 无符号数字
-- zerofill  以0填充  int(5)  00100  1000000

-- 格式化类: NumberFormat   0 #

2 小数类型

-- float(m,n)  学生的成绩  商品单价
-- double(m,n)

m: 规定小数的总位数
n:限定小数点后面有几位数据
double(5,2)  111.23

-- 与钱相关的一些数据 
-- BigDecimal
-- decimal(m,n) 定点数  优先

3 字符类型

-- char(m)  定长  性别char(1) 手机号码  身份证号码
-- varchar(m) 可变长度  用户名 简介
m: 限定存储字符个数。
char(5)  'abc' 存储的时候还是存储5个字符'abc__'  查询的时候 先trim 再展示数据
varchar(5) 'abc' 存储就是3个字符 
    
-- text
-- longtext  

String

4 日期类型

-- 年月日  date
-- 年月日 时分秒 datetime  timestamp
-- 时分秒 time
-- 年 year(2/4) 2022 22

3.3 DML

insert  delete  update

1. insert

对于insert  有几行记录受影响? >=1

-- 1. 对所有的列都新增新的数据
insert into 表名 values (数据1,....数据n); -- 有几个字段 就新增几个数据即可


mysql> insert into tb_userinfo values (
    -> 1,'jackMa','m','111111',40,6666666,
    -> '1234','1977-01-01','2020-01-01 12:00:00',null,null
    -> );

mysql> select * from tb_userinfo;
+------+--------+--------+--------+------+--------------+----------+------------+---------------------+-------------+-----------------+
| id   | name   | gender | phone  | age  | balance      | password | birthday   | create_time         | update_time | last_login_time |
+------+--------+--------+--------+------+--------------+----------+------------+---------------------+-------------+-----------------+
|    1 | jackMa | m      | 111111 |   40 | 6666666.0000 | 1234     | 1977-01-01 | 2020-01-01 12:00:00 | NULL        | NULL            |
+------+--------+--------+--------+------+--------------+----------+------------+---------------------+-------------+-----------------+

-- 在很多情况下  不需要对所有的列赋值  指定列新增记录
-- 2. insert into 表名 (列名1,...列名n) values (数据1,....数据n);

mysql> insert into tb_userinfo (id,name,password,create_time) values (2,'ponyMa','1234',now());
Query OK, 1 row affected (0.05 sec)


mysql> insert into tb_userinfo (id,name,create_time) values (3,'马云',now());
ERROR 1366 (HY000): Incorrect string value: '\xC2\xED\xD4\xC6' for column 'name' at row 1

-- 不能存储汉字数据?
mysql> show create database mydb;
+----------+-----------------------------------------------------------------+
| Database | Create Database                                                 |
+----------+-----------------------------------------------------------------+
| mydb     | CREATE DATABASE `mydb` /*!40100 DEFAULT CHARACTER SET latin1 */ |
+----------+-----------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> alter database mydb CHARACTER SET UTF8;  -- 修改指定数据库的编码格式
Query OK, 1 row affected (0.00 sec)

mysql> show create database mydb;
+----------+---------------------------------------------------------------+
| Database | Create Database                                               |
+----------+---------------------------------------------------------------+
| mydb     | CREATE DATABASE `mydb` /*!40100 DEFAULT CHARACTER SET utf8 */ |
+----------+---------------------------------------------------------------+


-- 修改完数据库的编码格式  还是会有可能出现不能存储中文问题
-- 有可能是因为这张表  他是在修改编码格式之前创建好的。
-- 对于cmd这个客户端而言  没法修改  只能先删除 再创建新的一张表

-- 局部修改指定的一个数据库的编码格式  。

mysql> show variables like '%character%';
+--------------------------+---------------------------------------------------------+
| Variable_name            | Value                                                   |
+--------------------------+---------------------------------------------------------+
| character_set_client     | gbk                                                     |
| character_set_connection | gbk                                                     |
| character_set_database   | utf8                                                    |
| character_set_filesystem | binary                                                  |
| character_set_results    | gbk                                                     |
| character_set_server     | latin1                                                  |
| character_set_system     | utf8                                                    |
| character_sets_dir       | C:\Program Files\MySQL\MySQL Server 5.7\share\charsets\ |
+--------------------------+---------------------------------------------------------+

-- 全局修改mysql的服务器的编码格式:
-- my.ini
default-character-set=utf8
character-set-server=utf8

-- 修改了核心配置文件 重新启动mysql的服务。

-- 一次新增多条记录  性能比较高
-- 3. insert into 表名 (列1....列n) values (数据1,....数据n),(数据1,....数据n),(数据1,....数据n);

2. update

一次更新一行记录。 带条件修改。条件语句 where

-- 1. update 表名 set 列1=新的数据,... 列n=新的数据;

-- 修改表里面所有的记录
mysql> update tb_userinfo set age=35,gender='m';


-- 2. update 表名 set 列1=新的数据,... 列n=新的数据  where 条件1 and/or 条件2;
mysql> update tb_userinfo set balance=7000,birthday=now() where id=4;

3. delete

删除.   删除一个  删除多个。

-- delete  from  表名;  --  删除表里面的所有的数据(清空表) 可以回滚

-- delete from 表名 where 条件1 and/or 条件2;

mysql> delete from tb_userinfo where id=3 or id=4;
mysql> delete from tb_userinfo where id in (1,2);

4. 客户端工具

// 1. navicat 
// 2. sqlyog
// 3. mysqlFront

5.约束

限定字段数据。 数据需要满足一些规则。

  • 表级约束 primary key
  • 行级约束: not  null  default  unique   primary key

5.1 not null

非空约束  。  限定列的数据不能为null。

-- INSERT INTO tb_product (id,prod_price) VALUES (5,10); 
-- prod_name必须赋值  不能为null  not  null
-- 修改这个列的特征
DESC tb_product;
ALTER TABLE tb_product MODIFY prod_name VARCHAR(20) NOT NULL;


CREATE TABLE a1(
 id int not null,
 name varchar(20) not NULL
);

5.2 default

默认约束。  给指定列设置默认值。

-- CREATE TABLE a1(
--  id int not null,
--  name varchar(20) NOT NULL DEFAULT '无名氏',
--  age int
-- );

-- ALTER TABLE a1 modify name varchar(20) not null DEFAULT '无名氏';
-- DESC a1;

-- INSERT INTO a1 (id,`name`,age) VALUES (1,null,20);

5.3 unique

unique。保证列的数据唯一性。 也称为唯一性索引。

NOT NULL+ UNIQUE ===> PRI

索引----> 目录  效率比较快的。   底层是结合一些算法维护索引。
创建唯一性约束 自带索引的。
有索引的字段在查询的语句中  比没有索引列 性能更快。

推荐在sql中大量创建索引。 第4阶段。

-- CREATE TABLE a1(
--  id int not null,
--  name varchar(20) NOT NULL UNIQUE DEFAULT '无名氏',
--  age int NOT null
-- );

-- 在NOT NULL UNIQUE 下 默认约束就没有意义
-- NOT NULL+ UNIQUE ===> PRI
-- ALTER TABLE a1 modify name varchar(20) UNIQUE;

5.4 primary key

主键约束。 数据特征:  not null+unique

也可以称为主键索引。 自带索引。

--  1. 一张表里面只有1个主键约束。
--  2. 任意类型的列都可以充当主键列。-----> 整型(自增)+字符类型(uuid)
--  3. 可以有多个列同时充当一个主键列。(联合主键)---->必须使用表级约束

表设计: 理论上遵循3大范式
第1范式:  保证列的原子性。 列不可再分。  河南省郑州市高新  没有保证原子性。
 provice  city  area
第2范式:  在遵循第1范式的基础之上  保证行记录的唯一性。 id唯一。 一般都是主键约束。
第3范式:  在遵循第2范式的基础之上. 
    尽可能减少/不能出现数据/列的过度冗余。 
    主键列或者外键列的数据除外。可以允许冗余。
    
具体的表设计看具体的需求。

-- DROP TABLE a1;
-- 
-- CREATE TABLE a1(
--  id int PRIMARY KEY auto_increment,
--  name varchar(20) NOT NULL UNIQUE,
--  age int NOT NULL
-- );
-- 
-- DESC a1;

-- id: PRIMARY KEY 必须要唯一   手动维护唯一性???
-- mysql自己维护主键列id的数据  自己累增+1
-- 主键列是整型的话 一般都会与auto_increment 联合使用。
-- ALTER TABLE a1 MODIFY id int auto_increment;
-- id的数据自增了 在insert的时候 就不需要对id赋值 了
-- 自定义自增的初始值  默认1  每次自增+1
-- ALTER TABLE a1 auto_increment 1001;
-- SET GLOBAL auto_increment_increment=5;
-- 可以获得上一次新增的id的数据
-- SELECT LAST_INSERT_ID();
-- SELECT * FROM a1;

INSERT INTO a1 (`name`,age) VALUES ('张翠翠4',20);
SELECT * FROM a1;


-- create TABLE b(
--  id VARCHAR(100),
--  name VARCHAR(20),
--  PRIMARY KEY(id) -- 表级约束
-- );

-- DESC b;
-- 1.要么在代码里面 UUID 传过来一个唯一的字符串的数据
-- 2. 交给mysql服务器维护 id值  UUID()
INSERT INTO b (id,name) VALUES (UUID(),'tom');

-- CREATE TABLE c(
--  name VARCHAR(20),
--  pass VARCHAR(100),
--  age int,
--  PRIMARY key(name,pass)
-- );

-- desc c;
-- 场景: 一般经常出现在中间表里面、(维护其他多张表的关系)
INSERT INTO c(name,pass) VALUES ('tom','1234');

5.5 foreign key

外键约束。使用外键约束修饰的列 称为外键列。

1. 一张表里面可以有多个外键列
2. 外键约束维护多表关系的。
3. 一张表里面如果有外键列的话  这张表作为从表或者子表。
4. 外键列的数据要严格操作主表/基表里面的主键列的数据。

表与表之间的关系:
  1. 用户与购物车  1对1关系
  2. 购物车与购物项  一对多
      购物车里面有很多购物项  还有总价
      
  3. 购物项与商品 一对一
  
 得知:  
  4. 用户与商品 多对多

1. 一对一

-- 新增外键约束
-- tb_cart.uid  将这个列变为外键列
-- ALTER TABLE tb_cart ADD CONSTRAINT FOREIGN KEY (uid) REFERENCES tb_userinfo(id);

在外键约束下操作主表+子表数据:

-- 新增外键约束
-- tb_cart.uid  将这个列变为外键列
-- ALTER TABLE tb_cart ADD CONSTRAINT FOREIGN KEY (uid) REFERENCES tb_userinfo(id);

-- 一:有外键约束   删除/更新 RESTRICT
-- 新增用户信息
-- 1. 新增主表
-- INSERT INTO tb_userinfo (name) VALUES ('王五');
-- 2.删除主表
-- DELETE FROM tb_userinfo WHERE id =11; -- 子表没有参考主表的信息
-- DELETE FROM tb_userinfo WHERE id =1; 
   -- 不能删除  子表在使用这个数据 
	 -- 根本原因: 在外键约束里面   删除/更新 RESTRICT
-- 3. 修改主表信息
-- UPDATE tb_userinfo SET gender = 'n' WHERE id =1;

-- 操作子表
-- 1. 新增子表的数据
-- INSERT INTO tb_cart (total_money,uid) VALUES (1000,6); -- 这个数据必须存在于主表里面
-- 2. 删除子表的数据
-- DELETE FROM tb_cart WHERE id=1011;
-- 3. 修改子表的数据
-- UPDATE tb_cart SET total_money = 2000,uid=10 WHERE id = 1001;

-- 二:有外键约束   删除/更新 SET NULL
-- 删除主表
-- DELETE FROM tb_userinfo WHERE id =1;
-- 子表里面没有记录关联数据  直接删除
-- 有 会先将子表里面记录update为null  然后再删除主表的数据

-- 二:有外键约束   删除/更新 CASCADE  级联
-- 删除主表
-- DELETE FROM tb_userinfo WHERE id =6;

-- SELECT * FROM tb_userinfo;
-- SELECT * FROM tb_cart;

-- 总结: 外键约束可以维护多表数据。
-- 弊端: 性能低。不太推荐使用外键约束的。 外键列还正常使用。
-- 只需要将一个普通列看成外键列即可。 弱化外键思想。伪外键

2.一对多

一个购物车有多个购物项

3. 多对多

学生+老师  学生+课程

角色+权限

6. DQL

数据查询语言。 select

6.1.语法

SELECT [DISTINCT] 列的集合
FROM 表的集合 
[
WHERE 条件的集合 -- 过滤记录
GROUP BY 列的集合 -- 分组查询   使用指定的列进行分组
HAVING   条件的集合 -- 类似的where 过滤的  对分组之后的数据进行过滤
ORDER BY 列 ASC/DESC  -- 根据指定的列进行升序或者降序排列 默认升序 ASC
LIMIT ?/?,? -- 限定最后记录 分页查询       
]

6.2 基础查询

SELECT * FROM A; -- 表里面列很少的时候  *
SELECT ID ,NAME ,AGE FROM A; -- 列很多  指定列查询  提高sql的查询的性能

6.3 条件查询 where

	条件查询就是在查询时给出WHERE子句,在WHERE子句中可以使用如下运算符及关键字:
	=、!=、<>、<、<=、>、>=;
	BETWEEN…AND;是否满足一个区间范围  >=  <=
	IN(set);条件的集合
	IS NULL;
	AND; 连接多个条件的查询
	OR;or  满足其中一个条件就可以
	NOT;

-- 1. 条件查询
-- 	查询学生性别为女,并且年龄50的记录
-- SELECT * FROM stu WHERE gender='female' OR age=15;
-- 	查询学号为S_1001,S_1002,S_1003的记录
-- SELECT * FROM stu WHERE sid='s_1001' OR sid='s_1001'  OR sid='s_1003' ;
-- SELECT * FROM stu WHERE sid IN ('s_1001','s_1002','s_1003');
-- 	查询学号不是S_1001,S_1002,S_1003的记录
-- SELECT * FROM stu WHERE NOT sid  IN ('s_1001','s_1002','s_1003');
-- SELECT * FROM stu WHERE sid!='s_1001' AND sid!='s_1002'  AND sid!='s_1003' ;

-- 	查询年龄为null的记录
-- SELECT * FROM stu WHERE age IS NulL;
-- SELECT * FROM stu WHERE age IS NOT  NulL;

-- 	查询年龄在20到40之间的学生记录
-- SELECT * FROM stu WHERE age>= 20 AND age<=40;
-- SELECT * FROM stu WHERE age BETWEEN 20 AND 40;

-- 	查询性别非男的学生记录
-- SELECT * FROM stu WHERE gender!='male' OR gender is null;

6.4 模糊查询 like

与where一起使用。  模糊匹配

-- 	查询姓名由5个字母构成的学生记录
-- 使用通配符:  统配任意一个字符  _ 
-- SELECT * FROM stu WHERE sname LIKE '_____';
-- 	查询姓名以“z”开头的学生记录
-- %: 统配的是任意数量的字符数据
-- SELECT * FROM stu WHERE sname LIKE 'z%';
-- SHOW VARIABLES LIKE '%character%';

-- 	查询姓名中第2个字母为“i”的学生记录
-- SELECT * FROM stu WHERE sname LIKE '_i%';
-- 	查询姓名中包含“a”字母的学生记录
-- SELECT * FROM stu WHERE sname LIKE '%a%';

6.5 字段控制查询

1. distinct 去重

只是对指定的列去重。

-- 3. DISTINCT  去重  看DISTINCT有哪些列
-- SELECT DISTINCT gender FROM stu;
-- 可以去重重复的行记录

2. ifnull

-- 计算员工的工资
-- 只要是查询语句  都会出现一张临时表
-- comm有值得记录 运算是ok
-- 列与null进行任意算术运算  最后的结果都是null
-- IFNULL(列名,新的数据) 列为null  使用指定的数据进行运算  否则还是自身的数据
-- SELECT empno,ename,sal,comm, (sal+IFNULL(comm,0)) FROM emp;

6.6 排序 order by

在代码里面排序:
 Arrays.sort()
 List.sort(Comparator c)
 Collections.sort(List l)    
 Collections.sort(List l,Comparator c)    
     
 List<Integer> list;      Integer implements Comparable 
 包装类型+String  
 
  List<UserInfo> list;

order by  字段1  ASC/DESC  , 字段2 ASC/DESC

-- 只要是查询一般都会排序 一般都是将最新的数据  展示在最前面
-- ORDER BY id/create_time(毫秒数) DESC
-- 查询学生的信息  根据年龄进行升序或者降序排列
-- SELECT * FROM stu ORDER BY age ASC, sid DESC;

6.7 分组函数

也可以称为  “聚合函数”。------> 有且只有1个记录(只有1个结果)

	COUNT(列):统计指定列不为NULL的记录行数;
	MAX(列):计算指定列的最大值,如果指定列是字符串类型,那么使用字符串排序运算;
	MIN(列):计算指定列的最小值,如果指定列是字符串类型,那么使用字符串排序运算;
	SUM(列):计算指定列的数值和,如果指定列类型不是数值类型,那么计算结果为0;
	AVG(列):计算指定列的平均值,如果指定列类型不是数值类型,那么计算结果为0;


-- 	查询emp表中记录数:
-- SELECT COUNT(empno),COUNT(comm),COUNT(*),COUNT(1) FROM emp;
-- 	查询emp表中月薪大于2500的人数:
-- 	统计月薪与佣金之和大于2500元的人数:
-- SELECT COUNT(*) FROM emp WHERE (sal+IFNULL(comm,0))>2500;

-- 在查询的时候 会出现的很多新的字段 这些的名称 有可能很复杂
-- 一般进行别名处理  [AS] 
-- 对表起别名: 多表关联的时候  
-- SELECT MAX(sal),MIN(e.sal),SUM(sal),AVG(sal),SUM(sal)/COUNT(*) AS avgSal  FROM emp AS e;

-- SELECT * from emp where sal = (SELECT MAX(sal) FROM emp);

6.8 分组查询 group by

根据指定的列进行分组查询。

-- 分组查询
-- 	查询每个部门的部门编号和每个部门的工资和:
-- 先分组  再进行分组运算
-- -- 	查询每个部门的部门编号以及每个部门的人数:
-- SELECT deptno,sum(sal) '每个部门工资和',COUNT(*) '每个部门的员工数量'  FROM emp  GROUP BY deptno;
-- 	查询每个部门的部门编号以及每个部门员工工资大于1500的人数:
-- SELECT deptno,count(*) FROM emp WHERE sal>1500 GROUP BY deptno;

6.9 having

作用与where一致。

-- 查询薪资>1500 的员工信息
-- SELECT * FROM emp WHERE sal>1500;
-- SELECT * FROM emp HAVING sal>1500;
-- 与分组相关
-- 查询工资总和大于9000的部门编号以及工资和:
-- > 1111 - Invalid use of group function  where 不能与组函数一起使用
-- 对比where vs having  : 与条件总和使用  过滤数据
-- 1. 从位置 where在GROUP BY之前  having在GROUP BY之后
-- 2. where 不能与组函数一起使用  having就是对分组之后的数据进行过滤 因此可以一起使用
-- SELECT deptno,sum(sal) AS sum FROM emp  GROUP BY deptno HAVING sum(sal)>9000 ;

6.10 多表关联查询

1. 等值连接

连接的条件是一个 =

-- 多表关联查询
-- 1. 查询员工信息,要求显示员工号,姓名,月薪,部门名称 
-- 等值关联查询: 查询的条件是=
SELECT
  e.empno,e.ename,e.sal,d.dname
FROM emp AS e,dept AS d   -- 查询多张表 使用 , 
WHERE e.deptno=d.deptno;   -- 多表关联的时候 分析表与表的关系(外键列+主键列)

-- 多表关联的时候 有可能多张表里面出现很多重名列 
-- 1. 使用表名限定
-- 2. 使用别名 表的别名
-- 关联2张表查询: 条件至少1个   关联n张表查询: n-1

-- 查询指定用户的购物车信息
-- SELECT 
--  u.id,u.`name`,c.total_money
-- FROM 
--  demo.tb_userinfo AS u, demo.tb_cart AS c
-- WHERE
--  u.id =1  AND u.id = c.uid; 
-- 查询用户购买的购物项(小计)
-- SELECT
--  u.id,u.`name`,c.total_money,ci.buy_num,ci.money
-- FROM
--  demo.tb_userinfo AS u, demo.tb_cart AS c,demo.tb_cart_item AS ci 
-- WHERE
--  u.id =1 AND u.id=c.uid AND c.id=ci.cid;
-- 查询用户购买的商品信息
-- SELECT
--  u.id,u.`name`,c.total_money,p.prod_name,p.prod_price,p.prod_image,ci.buy_num,ci.money
-- FROM
--  demo.tb_userinfo AS u, demo.tb_cart AS c,demo.tb_cart_item AS ci ,demo.tb_product AS p
-- WHERE
--  u.id =1 AND u.id=c.uid AND c.id=ci.cid AND ci.pid=p.id;

2. 不等值连接

连接条件不是一个 =

-- 查询员工信息,要求显示:员工号,姓名,月薪,部门名称,薪水的级别
-- SELECT
--   e.empno,e.ename,e.sal,s.GRADE
-- FROM
--   emp AS e, salgrade AS s
-- WHERE
--   e.sal BETWEEN s.LowSAL AND s.HISAL
-- ORDER BY e.sal;

SELECT
  e.empno,e.ename,e.sal,s.GRADE,d.dname,d.loc
FROM
  emp AS e, salgrade AS s,dept AS d
WHERE
  e.sal BETWEEN s.LowSAL AND s.HISAL AND e.deptno=d.deptno
ORDER BY e.sal;

3. 自连接

本表与本表关联查询。

-- 自连接
-- 查询员工姓名和员工的老板的名称
-- 本表与本表有关系: 需要将一张表  看成多张表  别名  使用条件分析
SELECT
 e1.*,   e2.ename AS boss_name
FROM
emp AS e1, emp AS e2
WHERE e1.mgr=e2.empno;

4. 外连接

-- 查询的所有的员工信息并展示上级信息
-- 基准表是: 员工表
-- 外连接
-- 1. 内外连接  ---->普通的关联查询  INNER OUTER JOIN  INNER JOIN...ON/WHERE
-- 2. 左外连接 LEFT JOIN...ON  以左表为基准 右表里面没有的数据使用null或者0填充
-- 3. 右外连接 RIGHT JOIN...ON 以右表为基准 左表里面没有的数据使用null或者0填充
-- SELECT
--  e1.*,   e2.ename AS boss_name
-- FROM
-- emp AS e1 INNER JOIN  emp AS e2
-- ON e1.mgr=e2.empno
-- WHERE 1=1;

-- SELECT
--  e1.*,   e2.ename AS boss_name
-- FROM
-- emp AS e1 LEFT JOIN  emp AS e2
-- ON e1.mgr=e2.empno;

-- 按部门统计员工数,部门号,部门名称,人数 count()
-- 统计每个部门的员工数
-- SELECT
--   d.*,count(*) '部门人数'
-- FROM 
--  dept AS d, emp AS e
-- WHERE 
--  d.deptno=e.deptno 
-- GROUP BY d.deptno ;

-- SELECT
--   d.*, count(e.empno) '部门人数'
-- FROM 
--  emp AS e RIGHT JOIN  dept AS d  ON  d.deptno=e.deptno 
-- GROUP BY d.deptno ;
--

-- 查询员工信息: 展示员工所在的部门名称 员工的薪资等级  还有员工的上级领导名称
SELECT
 e1.*,d.dname,s.GRADE,e2.ename
FROM
emp AS e1 LEFT JOIN emp AS e2 ON e1.mgr=e2.empno
LEFT JOIN dept AS d ON e1.deptno=d.deptno,salgrade AS s 
WHERE
  e1.sal BETWEEN s.LowSAL AND s.HISAL;

6.11 子查询

-- 查询员工信息  他的薪资是20号部门平均薪资
-- SELECT avg(sal) FROM emp WHERE deptno=20;
-- SELECT * FROM emp WHERE sal=2175;
-- 子查询: 查询的条件是未知
SELECT * FROM emp WHERE sal=(SELECT avg(sal) FROM emp WHERE deptno=20);

6.12. 集合查询

将多个结果集转换成1个结果集。

-- 查找所有的用户信息
-- SELECT * FROM user0;
-- SELECT * FROM user1;
-- SELECT * FROM user2;
-- 集合运算   UNION  vs  UNION ALL
-- 将多个结果集  合成1个
-- UNION ALL: 不去重  UNION: 去除重复的行记录

-- SELECT * FROM user0
-- UNION
-- SELECT * FROM user1
-- UNION
-- SELECT * FROM user2;

-- SELECT id,name FROM USER0
-- UNION
-- SELECT id,name FROM USER1
-- UNION
-- SELECT id,name FROM USER2;

-- 在mysql里面 有几种去重的操作?
-- 1. DISTINCT
-- 2. UNION
-- 3. GROUP BY

6.13 分页查询

-- 分页查询员工信息
-- size=4
-- page=1
-- SELECT count(*) FROM emp;  15/4=3
-- LIMIT size; 从第1条开始查询 查size条数据  只能查询第1页的数据
-- LIMIT startIndex,size; 从第startIndex+1条开始查询 查size条
-- 第1页
SELECT * FROM emp LIMIT 0,4;

-- 第2页
SELECT * FROM emp LIMIT 4,4;

-- 第3页
SELECT * FROM emp LIMIT 8,4;

-- 第4页
SELECT * FROM emp LIMIT 12,4;

-- SELECT * FROM emp LIMIT (page-1)*size,size;

7.函数

自学

8. 数据库存储引擎

9. 数据备份

1. 物理备份  C:\ProgramData\MySQL\MySQL Server 5.7\Data
2. 命令行备份
    C:\Users\JAVASM>mysqldump -uroot -proot demo >> D:\\a.sql
    -- 将demo库里面的所有的表都进行了备份
C:\Users\JAVASM>mysqldump -uroot -proot demo tb_userinfo tb_cart >> D:\\b.sql
    -- 将demo库里面的指定的表的结构+数据进行备份
    
    在连接成功前提下  source 文件路径;   source d:\\a.sql
    
3. 使用图形化的工具
    导入/导出sql文件。
    
4. 使用图形化的工具---->备分

10.课堂练习

1.MySQL之常用函数

1. 字符串函数

函数

功能

concat(str1,str2,…)

连接字符串

insert(str,pos,len,newstr)

字符串str从第pos位置开始的len个字符替换为新字符串newstr

lower(str)

转成小写

upper(str)

转成大写

length(str)

返回字符串str的长度

char_length(str)

返回字符串str的长度

lpad(str,ien,padstr)

返回字符串str,其左边由字符串padstr填补到len字符串长度

rpad(str,len,padstr)

返回字符串str,其右边由字符串padstr填补到len字符串长度

trim(str)

去掉字符串str前缀和后缀的空格

repeat(str,count)

返回str重复count次的结果

replace(str,from_str,to_str)

用字符串to_str替换字符串str中所有的字符串from_str

substring(str,pos,len)

从字符串str的pos位置起len个字符长度的子串

insert(str,pos,len,newstr):

  • INSERT('Football',2,4,'Play') 将“Football”从第 2 个字符开始长度为 4 的字符串替换为 Play,结果为“FPlayall”;
  • INSERT('Football',-1,4,'Play') 中的起始位置 -1 超出了字符串长度,直接返回原字符串;
  • INSERT('Football',3,20,'Play') 替换长度超出了原字符串长度,则从第 3 个字符开始,截取后面所有的字符,并替换为指定字符 Play,结果为“FoPlay”。

2. 数值函数

函数

功能

ABS(X)

返回X的绝对值

CEIL(X)

返回不小于X的最小整数(向上取整)

FLOOR(X)

返回不大于x的最大整数(向下取整),返回值类型bigint

MOD(X,Y)

返回x/y的模

RAND()

返回一个0~1之间的随机浮点数

ROUND(X,Y)

返回x的四舍五入的有y位小数的值

TRUNCATE(X,Y)

返回数字x截断位y位小数的结果

TRUNCATE(x,y)返回数值 x 保留到小数点后 y 位的值(与 ROUND 最大的区别是不会进行四舍五入)

SELECT TRUNCATE(1.23456,3);
---- 返回1.234

3. 日期和时间函数

函数

功能

CURDATE()

返回当前日期

CURTIME()

返回当前时间

NOW()

返回当前的日期和时间

WEEK(date)

返回指定日期为一年中的第几周

YEAR(date)

返回日期的年份

HOUR(time)

返回time的小时值

MINUTE(time)

返回time的分钟值

MONTHNAME(date)

返回date的月份名

DATEDIFF(expr,expr2)

返回起始时间expr和结束时间exrp2之间的天数

DATE_FORMAT(date,fmt)

返回按字符串fmt格式化日期date值

from_unixtime(unix_timestamp,”%Y-%m-%d %H:%i:%S”)常用来将毫秒数转换为时间格式

%M 月名字(January……December)

%W 星期名字(Sunday……Saturday)

%D 有英语前缀的月份的日期(1st, 2nd, 3rd, 等等。)

%Y 年, 数字, 4 位

%y 年, 数字, 2 位 20

%a 缩写的星期名字(Sun……Sat)

%d 月份中的天数, 数字(00……31)

%e 月份中的天数, 数字(0……31)

%m 月, 数字(01……12)

%c 月, 数字(1……12)

%b 缩写的月份名字(Jan……Dec)

%j 一年中的天数(001……366)

%H 小时(00……23)

%k 小时(0……23)

%h 小时(01……12)

%I 小时(01……12)

%l 小时(1……12)

%i 分钟, 数字(00……59)

%r 时间,12 小时(hh:mm:ss [AP]M)

%T 时间,24 小时(hh:mm:ss)

%S 秒(00……59)

%s 秒(00……59)

%p AM或PM

%w 一个星期中的天数(0=Sunday ……6=Saturday )

%U 星期(0……52), 这里星期天是星期的第一天

%u 星期(0……52), 这里星期一是星期的第一天

%% 一个文字“%”。

4. 高级函数

case见mysql作业

更多参考:

MySQL常用函数大全(总结篇)_zeng_ll的博客-CSDN博客_mysql常用函数大全

11.课后作业

1.作业1

1.创建student和score表

CREATE TABLE student (
id INT(10) NOT NULL PRIMARY KEY , #学生ID 自增
name VARCHAR(20) NOT NULL , #学生姓名
sex VARCHAR(4) , #学生性别
birth YEAR, #学生出生年份
department VARCHAR(20) , #所在院系
address VARCHAR(50) #家庭住址
);

创建score表。SQL代码如下:
CREATE TABLE score (
id INT(10) NOT NULL PRIMARY KEY AUTO_INCREMENT , #自增ID
stu_id INT(10) NOT NULL , #学生ID ,外键创建可有可无
c_name VARCHAR(20) , #学科名称
grade INT(10) #分数
);

2.添加记录

向student表插入记录的INSERT语句如下:
INSERT INTO student VALUES( 901,'张老大', '男',1985,'计算机系', '北京市海淀区');
INSERT INTO student VALUES( 902,'张老二', '男',1986,'中文系', '北京市昌平区');
INSERT INTO student VALUES( 903,'张三', '女',1990,'中文系', '湖南省永州市');
INSERT INTO student VALUES( 904,'李四', '男',1990,'英语系', '辽宁省阜新市');
INSERT INTO student VALUES( 905,'王五', '女',1991,'英语系', '福建省厦门市');
INSERT INTO student VALUES( 906,'王六', '男',1988,'计算机系', '湖南省衡阳市');
向score表插入记录的INSERT语句如下:
INSERT INTO score VALUES(NULL,901, '计算机',98);
INSERT INTO score VALUES(NULL,901, '英语', 80);
INSERT INTO score VALUES(NULL,902, '计算机',65);
INSERT INTO score VALUES(NULL,902, '中文',88);
INSERT INTO score VALUES(NULL,903, '中文',95);
INSERT INTO score VALUES(NULL,904, '计算机',70);
INSERT INTO score VALUES(NULL,904, '英语',92);
INSERT INTO score VALUES(NULL,905, '英语',94);
INSERT INTO score VALUES(NULL,906, '计算机',90);
INSERT INTO score VALUES(NULL,906, '英语',85);

3.查询student表的所有记录

select * from student;

4.查询student表的第2条到4条记录

select * from student limit 1,3;

5.从student表查询所有学生的学号(id)、姓名(name)和院系(department)的信息

select id,name,department from student;

6.从student表中查询计算机系和英语系的学生的信息

select * from student where department='计算机系' or department='英语系';

7.从student表中查询年龄1985~1990年份的学生信息

select * from student where birth between 1985 and 1990;

8.从student表中查询每个院系有多少人

select count(*) as '人数' from student group by department;

9.从score表中查询每个科目的最高分

select max(garde) as '最高分' from score group by c_name;

10.查询李四的考试科目(c_name)和考试成绩(grade)

select

st.name,sc.c_name,sc.garde

from student as st ,score as sc

where

st.name='李四' and st.id=sc.stu_id;

11.用连接的方式查询所有学生的信息和考试信息

select

st.*,sc.*

from

student as st, score as sc

where

st.id = sc.stu_id;

结果:六个人展示出10行记录,希望只展示6行记录

-- GROUP_CONCAT 一个人有多行记录,且值不一样,可拼到一起 前提:必须有分组
SELECT
s.`name`,GROUP_CONCAT(sc.c_name),GROUP_CONCAT(sc.garde)
FROM
student AS s, score sc WHERE s.id=sc.stu_id
GROUP BY s.id;

升级版,用case when 行转列(做数据报表和面试题)

语法一:简单函数,做等值判断 case字段 when数据 then数据 else数据 end

语法二:搜索函数,做条件判断 case when条件 then数据 .....(多个when) else数据 end

SELECT
s.`name`,
max(CASE sc.c_name WHEN '计算机' THEN sc.garde ELSE null END) AS '计算机成绩',
max(CASE sc.c_name WHEN '中文' THEN sc.garde ELSE null END) AS '中文成绩',
max(CASE sc.c_name WHEN '英语' THEN sc.garde ELSE null END) AS '英语成绩'
FROM
student AS s, score sc WHERE s.id=sc.stu_id GROUP BY s.id;

若求每个学生年龄处于人生的什么阶段 少年 12-18 青年 19-30 中年31-50 老年51+

SELECT
id,name,birth, (YEAR(NOW())-birth) AS '年龄',
CASE
WHEN (YEAR(NOW())-birth) BETWEEN 12 AND 18 THEN '少年'
WHEN (YEAR(NOW())-birth) BETWEEN 19 AND 30 THEN '青年'
WHEN (YEAR(NOW())-birth) BETWEEN 31 AND 50 THEN '中年'
ELSE '老年'
END AS '人生阶段'
FROM student;

-- 涨工资 <10000 1.5 10000-15000 1.3 15000-30000 1.1
-- CREATE table temp select * from emp; 创建临时表,复制粘贴emp表

SELECT
empno,ename,sal,
CASE
WHEN sal <10000 THEN sal*1.5
WHEN sal BETWEEN 10001 AND 15000 THEN sal*1.3
WHEN sal BETWEEN 15001 AND 30000 THEN sal*1.1
ELSE sal
END AS '涨薪之后的薪资'
FROM temp;

12.计算每个学生的总成绩

select

st.name,sum(sc.garde)

from

student as st ,score as sc

where

st.id=sc.stu_id

group by sc.stu_id;

13.计算每个考试科目的平均成绩

select

sc.c_name '考试科目',avg(sc.garde) '平均成绩'

from score as sc

group by sc.c_name;

14.查询计算机成绩低于95的学生信息

SELECT
s.*,c.c_name,c.garde
FROM
student AS s,score AS c
WHERE
s.id = c.stu_id AND c.garde<95 AND c.c_name='计算机';

15.将计算机考试成绩按从高到低进行排序

SELECT * FROM score WHERE c_name='计算机' ORDER BY greade DESC ;

16.查询姓张或者姓王的同学的姓名、院系和考试科目及成绩

SELECT s.*,c.c_name,c.greade FROM student AS s,score AS c WHERE s.id = c.stu_id AND (s.name like '张%' OR s.name like '王%');

17.查询都是北京的学生的姓名、年龄、院系和考试科目及成绩

SELECT s.*,c.c_name,c.greade FROM student AS s,score AS c WHERE s.id = c.stu_id AND s.address like '北京%';

2.作业2

建立如图所示的四张表,按照图示数据添加到对应的表中

表一 emp

表二 dept

表三 salgrade

表四 年度利润表

1. 查出至少有一个员工的部门。显示部门编号、部门名称、部门位置、部门人数。

-- SELECT
-- d.*,COUNT(e.empno)
-- FROM emp e,dept d
-- WHERE e.deptno=d.deptno GROUP BY e.deptno;
-- SELECT
-- d.*,COUNT(e.empno)
-- FROM emp e LEFT JOIN dept d ON e.deptno=d.deptno
-- GROUP BY e.deptno HAVING COUNT(e.empno)>=2;

2. 列出所有员工的姓名及其直接上级的姓名。

-- SELECT
-- e1.*,e2.ename
-- FROM emp e1 LEFT JOIN emp e2 ON e1.mgr=e2.empno;

3. 列出受雇日期早于直接上级的所有员工的编号、姓名、部门名称。

-- SELECT
-- e1.*,e2.ename,d.dname
-- FROM emp e1 LEFT JOIN emp e2 ON e1.mgr=e2.empno
-- LEFT JOIN dept d ON e1.deptno=d.deptno
-- WHERE e1.hiredate<e2.hiredate;

4. 列出部门名称和这些部门的员工信息,同时列出那些没有员工的部门。

-- SELECT * FROM dept d LEFT JOIN emp e ON d.deptno=e.deptno ORDER BY d.deptno;

5. 列出最低薪金大于15000的各种工作及从事此工作的员工人数。

-- SELECT
-- job,count(*)
-- FROM emp GROUP BY job HAVING min(sal)>15000 ;

6. 列出在销售部工作的员工的姓名,假定不知道销售部的部门编号。

-- SELECT * FROM emp WHERE deptno=(SELECT deptno FROM dept WHERE dname='销售部');

7. 列出薪金高于公司平均薪金的所有员工信息,所在部门名称,上级领导,工资等级。

-- SELECT
-- e1.*,e2.ename,d.dname,s.GRADE
-- FROM emp AS e1, emp AS e2,dept AS d,salgrade AS s
-- WHERE e1.mgr=e2.empno AND e1.deptno=d.deptno AND e1.sal BETWEEN s.lowsal AND s.HISAL ;

-- SELECT
-- e1.*,e2.ename,d.dname,s.GRADE
-- FROM emp AS e1
-- LEFT JOIN emp AS e2 ON e1.mgr=e2.empno
-- LEFT JOIN dept AS d ON e1.deptno=d.deptno,salgrade AS s
-- WHERE e1.sal BETWEEN s.lowsal AND s.HISAL AND e1.sal >(SELECT avg(sal) FROM emp)
-- ORDER BY s.GRADE ;

8.列出与庞统从事相同工作的所有员工及部门名称。

-- SELECT
-- *
-- FROM
-- emp e,dept d
-- WHERE e.deptno=d.deptno AND e.ename!='庞统' AND e.job=(SELECT job FROM emp WHERE ename='庞统');

9.列出薪金高于在部门30工作的所有员工的薪金 的员工姓名和薪金、部门名称。

-- SELECT
-- *
-- FROM
-- emp e LEFT JOIN dept d ON e.deptno=d.deptno WHERE e.sal>(SELECT MAX(sal) FROM emp WHERE deptno=30);

10.查出年份、利润、年度增长比。

-- SELECT
-- p1.year,p1.zz, CONCAT(ROUND(((p1.zz-p2.zz)/p2.zz)*100,2),'%') AS '年度增长比'
-- FROM profit p1 LEFT JOIN profit p2 ON p1.year=p2.year+1 ORDER BY p1.`year`;

参考:

SQL语句的增删改查(详细)_宝宝要努力的博客-CSDN博客_增删改查https://blog.csdn.net/a88055517/article/details/6736284

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值