JavaSE(二十)MySQL

内存中;内存中的数据 当程序重启的时候 内存数据全部消失

数据做持久化操作 ;

数据库

1.1.相关概念 Mysql

  • 免费 开源

1.1.1.基本概念

DB(database):存储数据的仓库,其中的数据是有组织有关联的

DBMS(database management system)数据库管理系统 软件 系统,用来管理DB的

SQL (structure query language) 结构化查询语言 language,专门与DBMS通信的语言,所有DBMS(MySQL,Oracle,SQLserver等)都支持;

1.1.2. DBMS分类

存储位置的不同进行分类:

1,基于磁盘的存储,MySQL,Oracle,SQLServer 存储在底层文件中

2,基于内存的存储,Redis 非常适合做缓存,数据在内存中;

从数据间是否存在关系进行分类:

  1. 关系型数据库:MySQL,Oracle,SQLServer 数据之间有关系

  2. 非关系型数据库:Redis,mongodb nosql(not only sql)

1.1.3.数据表

DB数据库中有数据表(excel表),数据表由行和列组成,表中的每一列称为字段 每一行称之为 记录;

每一列类似Java中的属性,每一行类似Java中的对象;

1.1.4.字段的数据类型

1,整型

  • tinyint(2) 等同于byte的取值范围 -128-127

  • tinyint(1) 0 1 等同于java语言 boolean

  • int(n) n: 查询的时候单元格宽度 int(11) 显示宽度和数据类型的取值范围是无关的。如果插入了大于显示宽度的值,只要该值不超过该类型整数的取值范围,数值依然可以插入,而且能够显示出来。

  • bigint(n): 等价于long id 时间:毫秒数

2,小数

  • float(M,D),M称为精度,表示总共 的位数;D表达标度,表示小数的位数 12.345

  • double(m,d):

  • decimal(m,n): BigDecimal DECIMAL 的存储空间并不是固定的,而由精度值 M 决定,占用 M+2 个字节

3,字符型 没有字符和字符串的区别 也就没有单引号和双引号的区别 '张三' "张三"

  • char(4) :固定长度的字符类型,char(4)不管是存入几个字符,都将占用4个符号的字节

  • VARCHAR 和 TEXT 类型是变长类型,其存储需求取决于列值的实际长度,一个 VARCHAR(10) 列能保存一个最大长度为 10 个字符的字符串

  • MySQL不区分字符和字符串,单引号和双引号类似;

4,日期型

  • date: 年月日

  • datetime: 年月日 时分秒

  • timestamp: 年月日 时分秒 时间戳 数值;根据时区显示时间;

1.2.SQL语句

结构化查询语言,sql语句不区分大小写

DDL(Data Definition Language):数据定义语言 create drop alter
DML(Data Manipulation Language): insert delete update
DQL(Data Query Language): select
DCL(Data Control Language):commit rollback

1.2.1.DDL语句

1,创建一个表 t_stu,SQL中多个单词使用_下划线分隔

  • sql语句不区分大小写 多个单词使用_下划线分隔

​
-- 学生信息表
create TABLE tb_stu(
    id INT,
    sname VARCHAR(255),
    sgender CHAR(1),
    age INT,
    score FLOAT(4,2),
    birthday datetime,
    -- 最后一个字段没有逗号
    createtime date
)

2,alter修改表结构

-- 新增一个字段
ALTER TABLE t_stu ADD updatetime DATE;
-- 删除一个字段
ALTER TABLE t_stu DROP updatetime;
-- 修改表字段的数据类型
ALTER TABLE t_stu MODIFY sgender VARCHAR(1);
-- 修改表名
ALTER TABLE t_stu RENAME to stu;

3,drop

-- 删除数据库的命令
DROP DATABASE db_test; 
-- 删除数据表
DROP TABLE tb_test;

1.2.2. DML语句 insert delete update

1,insert 插入一行记录

-- 对所有字段依次赋值 VALUES和VALUE一样
insert INTO stu VALUES(1,'anne','m',16,6.6,'2020-10-22 11:33:20','2020-10-22');
-- 一次插入多条记录
insert INTO stu VALUE(2,'tom','m',16,6.6,'2020-10-22 11:33:20','2020-10-22'),(3,'jason','m',16,6.6,'2020-10-22 11:33:20','2020-10-22');
-- 指定字段插入
INSERT INTO stu(sid,sname) VALUES(2,'tom');

2,删除 行/记录

-- 指定条件进行删除记录
DELETE FROM stu WHERE sid=2;

3, 更新记录,多个字段之间使用逗号

-- 修改表记录内容
UPDATE stu SET age=19,score=99.99 WHERE sid=1;

1.2.3.DQ(query)L语句 select

0.基本语法

select selection_list /*要查询的字段,多个字段用逗号隔开*/
from table_list /*要查询的表名称*/
[where condition /*筛选记录的条件*/
 group by grouping_clounms /*对结果进行分组*/
 having condition /*对分组后的记录进行条件筛选*/
order by cloumns /*对结果进行排序*/
 limit  /*对记录总数进行限定*/]
  • select后面可以是表中的字段,常量值,表达式,函数;查询的结果是一个虚拟的表格;

1,基础查询,查询所有的列

-- 
SELECT * FROM t_stu;
-- 指定字段进行查询
SELECT sid,sname FROM t_stu;

2,条件查询

  • 按条件表达式筛选,> < = !=( <>不等于) >= <=

  • 逻辑表达式筛选 && || !( 等价于 and ,or,not)

  • between and(not between and) ,in(列表中的值不支持通配符), is null(is not null)

    • null的比较使用的is

-- 指定某一个条件进行查询
SELECT * FROM t_stu WHERE courseid=2 
-- AND 是两个条件都要满足
SELECT * FROM t_stu WHERE courseid=2 AND score>60;
-- OR是条件只要满足一个就行
SELECT * FROM t_stu WHERE courseid=2 OR score>60;
-- 查询sid为 1,6,8的记录,属于某个集合
SELECT * FROM t_stu WHERE sid IN(1,6,8);
-- 查询sid不属于 1,6,8的记录
SELECT * FROM t_stu WHERE sid  NOT IN(1,6,8);
-- 查询记录某个字段为null 
SELECT * FROM t_stu WHERE sgender is null;
SELECT * FROM  tb_stu WHERE updatetime IS NOT null;
--  查询成绩在70到90区间范围内的记录
SELECT * FROM t_stu WHERE score BETWEEN 70 AND 90;
-- 性别非男的记录 <>和!= 都是 不等于
select * FROM t_stu WHERE sgender <> 'm';
select * FROM t_stu WHERE sgender != 'm';

3,模糊查询,处理字符类型

%:表示匹配0或多个字符

_:任意一个字符

-- 名字由3个字母组成
SELECT * FROM t_stu WHERE sname LIKE '___';
-- 名字由j 开头
SELECT * FROM t_stu WHERE sname LIKE 'j%';
-- 第二个字母为a 的学生记录
SELECT * FROM t_stu WHERE sname LIKE '_a%';
-- 查询姓名中包含字母a的记录
SELECT * FROM t_stu WHERE sname LIKE '%a%';
-- 模糊查询 address是地址字段
SELECT * FROM t_stu WHERE address LIKE '北京市%';
SELECT * FROM t_stu WHERE address LIKE '北京市__';
SELECT * FROM t_stu WHERE sname LIKE '张%';

4,去重查询&起别名

  • 表或者字段还可以起别名,起别名是便于理解,如果查询的字段有重名情况使用别名可以区分,

  • AS可省略 使用空格

--  查询学生表中的所有性别
SELECT DISTINCT sgender FROM t_stu ;
-- DISTINCT去重 后面有多个字段 当这多个字段的值都相同的时候认为是重复的
SELECT DISTINCT sgender,age FROM t_stu;
-- 给查询出的字段起别名 AS是可以省略的 使用空格
SELECT age AS 年龄,sname AS 姓名 FROM  tb_stu;
SELECT sid a,sname b,sgender gender,score c FROM t_stu;

5,排序 order by子句可以跟单个字段,多个字段,表达式,函数,别名

-- 查询所有学生记录,按成绩进行降序排序
-- 缺省是ASC升序
SELECT * FROM t_stu ORDER BY score DESC;
-- 查询所有学生记录,首先先按成绩进行降序排序,如果成绩相同,按名字进行升序排序
SELECT * FROM t_stu ORDER BY score DESC, sname ASC;

6,组函数/聚合函数/分组函数

用作统计使用,又称为聚合函数或者统计函数或者组函数

  • 聚合函数是用来做纵向运算的函数:

  • COUNT(字段):统计指定列不为NULL的记录行数;一般使用count(*)统计行数

  • MAX(字段):计算指定列的最大值,如果指定列是字符串类型,那么使用字符串排序运算;

  • MIN(字段):计算指定列的最小值,如果指定列是字符串类型,那么使用字符串排序运算;

  • SUM(字段):计算指定列的数值和,如果指定列类型不是数值类型,那么计算结果为0;

  • AVG(字段):计算指定列的平均值,如果指定列类型不是数值类型,那么计算结果为0;

sum,avg一般处理数值型,

max,min,count可以处理任意数据类型

分组函数都忽略了null值,可以和distinct搭配使用

注意点:组函数可以出现多个,但是不能嵌套;如果没有group by 子句,结果集中所有行数作为一组

-- 查询emp表中有佣金的人数,统计指定列不为NULL的记录行数
SELECT count(comm) a FROM emp;
-- SELECT 200+null;
SELECT count(empno) 总人数 FROM emp;
SELECT count(*) 总人数 FROM emp;
SELECT count(1) 总人数 FROM emp;
-- 查询emp表中有佣金的人数
SELECT count(comm) from emp;
-- 查询emp表中月薪大于2500的人数:
SELECT * FROM emp WHERE sal>2500;
-- 统计月薪与佣金之和大于2500元的人数: ifnull(表达式1,表达式2)  如果表达式1为null那么取表达式2的值,否则取表达式1的值
SELECT * FROM emp WHERE sal+ifnull(comm,0) >2500;
-- 查询有佣金的人数,以及有领导的人数:
SELECT count(comm) FROM emp WHERE mgr is not null;
-- 查询所有雇员月薪和:
SELECT sum(sal) 总薪资  FROM emp;
-- 查询所有雇员月薪和,以及所有雇员佣金和:
SELECT sum(sal) 总薪资,SUM(comm) 总佣金 FROM emp;
-- 查询所有雇员月薪+佣金和
SELECT sum(sal+ifnull(comm,0)) 总佣金 FROM emp;
SELECT sum(sal)+sum(ifnull(comm,0)) 总佣金 FROM emp;
-- 统计所有员工平均工资
SELECT avg(sal) 平均薪资 FROM emp;
-- 查询最高工资和最低工资
SELECT max(sal),min(sal) FROM emp;

7,分组查询 group by

查询出来的字段要求是group by后的字段,查询字段中可以出现组函数

select 后面的字段 是分组字段,不要出现其他字段

group by后面可以跟聚合函数 可以起别名

--  查询每个部门的部门编号和每个部门的工资和
SELECT deptno,SUM(sal) FROM emp GROUP BY deptno;
--  查询每个部门的部门编号以及每个部门的人数
SELECT deptno,SUM(sal),COUNT(1) FROM emp GROUP BY deptno;
--  查询每个部门的部门编号以及每个部门员工工资大于1500的人数:
SELECT deptno,COUNT(1) FROM emp WHERE sal>1500 GROUP BY deptno;
​

按多个字段分组,后面字段一致的为一组

-- 按job进行分类
SELECT COUNT(*),job FROM emp GROUP BY job;
-- 按job和mgr进行分类
SELECT COUNT(*),job,mgr FROM emp GROUP BY job,mgr;

8,having子句

where是对分组前进行过滤;having是对分组后进行过滤

where中不能出现分组/聚合函数,having中可以出现

where是比分组先执行的,having是在分组之后执行的;

having后面可以跟别名

-- 查询工资总和大于9000的部门编号以及工资和:
SELECT deptno,sum(sal)  FROM emp GROUP BY deptno HAVING sum(sal)>9000;
-- having中使用别名
SELECT deptno,sum(sal) 总薪资 FROM emp GROUP BY deptno HAVING 总薪资>9000;
-- 查询部门员工个数大于3的,having中使用了别名
SELECT COUNT(1) cc,deptno FROM emp GROUP BY deptno HAVING cc>3;

9,limit 查询

分页查询,分页功能

-- 第一位表示起始索引位置,第二位表示总的长度(总的记录数);在分页中会使用
SELECT * FROM emp LIMIT 1,5;
SELECT * FROM emp LIMIT 5; 等价与 SELECT * FROM emp LIMIT 0, 5;

select完整语法使用

SELECT deptno,count(1),sum(sal) allsum FROM emp WHERE sal>1500 GROUP BY deptno HAVING sum(sal)>7000 ORDER BY allsum desc LIMIT 2;

10,多表查询/关联查询

内连接

  • 多表等值连接的结果是多表的交集部分,N表连接,至少需要N-1个连接条件,没有顺序要求,一般起别名

  • 非等值连接,只要不是等号连接的都是非等值连接

外连接,有主表有从表,主表肯定会显示完整的内容

  • 左外连接,以左表为主

  • 右外连接,以右表为主

-- 查询员工信息,要求显示员工号,姓名,月薪,部门名称
-- 笛卡尔积 (a, b) (1,2,3) --(a,1) (a,2) (a,3) (b,1) (b,2) (b,3)--》会生成一个中间表
-- 多表查询,关联条件使用的是等号
-- 查询员工信息,要求显示员工号,姓名,月薪,部门名称  等值连接
SELECT empno,ename,sal,emp.deptno,dname FROM emp,dept WHERE emp.deptno=dept.deptno;
-- 给表起别名
SELECT empno,ename,sal,a.deptno,dname FROM emp a,dept b WHERE a.deptno=b.deptno;
-- 非等值连接
-- 查询员工信息,要求显示:员工号,姓名,月薪,薪水的级别
SELECT empno,ename,sal,GRADE FROM emp e,salgrade sa WHERE e.sal BETWEEN sa.LowSAL AND sa.HISAL; 
​
-- 外连接
-- 查询员工信息,要求显示员工号,姓名,月薪,部门名称 使用内连接和等值连接等同
SELECT empno,ename,sal,emp.deptno,dname FROM emp INNER JOIN dept on emp.deptno=dept.deptno;
-- 左外连接(左连接) 左边的表内容全部显示,右边的表没有的以null进行填充
SELECT empno,ename,sal,emp.deptno,dname FROM emp LEFT JOIN dept on emp.deptno=dept.deptno;
-- 右外连接,右表内容全部显示,左表没有的以null进行填充
SELECT empno,ename,sal,emp.deptno,dname FROM emp RIGHT JOIN dept on emp.deptno=dept.deptno;
​

ON后面的条件(ON条件)和WHERE条件的区别:

ON条件:是过滤两个链接表笛卡尔积形成中间表的约束条件。

WHERE条件:在没有ON的单表查询中,是限制物理表或者中间查询结果返回记录的约束。在两表或多表连 接中是限制连接形成最终中间表的返回结果的约束。 ​建议: ​ ON只进行连接操作,WHERE只过滤中间表的记录

11,自连接,通过别名,将同一张表视为多张表;

什么情况下使用自连接;同一张表中某个字段要去关联另外一个字段

-- 查询员工姓名和员工的老板的名称
SELECT e1.empno,e1.ename,e2.empno,e2.ename  FROM emp e1, emp e2 WHERE e1.mgr=e2.empno;

12,子查询

-- 查询工资为20号部门平均工资的员工信息
SELECT * FROM emp WHERE sal>(SELECT AVG(sal) FROM emp GROUP BY deptno HAVING deptno=20);

1.3.约束,是为了数据的正确性

1.非空约束,一定要给值才能插入

  • NOT NULL

CREATE TABLE a(
    id INT NOT NULL,
    sname VARCHAR(20)
)
    
 --  提示错误:Field 'id' doesn't have a default value

2.唯一性约束,值不能重复

CREATE TABLE b(
    id INT not NULL UNIQUE
    )

3.默认约束,给一个默认值

CREATE TABLE c(
    id INT not NULL DEFAULT 6,
    sname VARCHAR(3)
    )

4.主键约束,主键列自动增长,无需赋值,表格必须要有一个主键 一张表中最多只有一个主键

CREATE TABLE t_stu(
-- 主键自增
    sid INT PRIMARY KEY auto_increment,
    sname VARCHAR(10) NOT NULL,
    sgender char(1),
    score FLOAT(4,1) NOT NULL,
    birthday TIMESTAMP,
    sutid VARCHAR(30) UNIQUE
    )

5.外键约束

一张表的外键 代表着另外一张表的主键,外键的值必须从另外一张表的主键中进行选择

ALTER TABLE t_stu add CONSTRAINT fk_cid FOREIGN KEY(courseid) REFERENCES course(id);

标志列:自增长列

一个表只能有一个标志列

#设置递增的初始值
ALTER TABLE t_t5 auto_increment=1000;
-- 设置步长
SET auto_increment_increment=2;
-- 查看标志列起始和步长
SHOW VARIABLES LIKE '%auto_increment%';

1.4.常用函数

注意:MySQL中的+就只有运算符的功能;会试图将字符型数值转换为数值型再继续操作,转换失败则转为0;若其中有null则结果为null;字符串可以使用concat函数拼接;

1.4.1.字符函数

length(str)得到的是字节个数 utf8中中文是3个字节

concat() 拼接字符串

upper /lower(str)

substr,substring 截取字串 MySQL的索引是从1开始的,截取的是字符长度

trim()

replace 替换全部符合的

sql中的索引是从1开始的

-- 字符串连接
SELECT concat('java','sun','aa');
-- length() 字节长度
SELECT length(sname),sname FROM tb_stu;
-- 字符长度
SELECT CHAR_LENGTH('java');
-- 去除前后空格
SELECT trim('  ja  va    ');
-- 重复指定次数
SELECT repeat('ja',4);
-- 字符串替换
SELECT REPLACE('javaoror','or','sun');
-- 截取字串
SELECT substring('javasun',5,3);

1.4.2.数学函数

  • round()四舍五入

  • ceil()向上取整

  • floor()向下取整

  • truncate()截断

  • mod()取余

-- 取绝对值
SELECT abs(-32);
-- 向上取最小整数
SELECT ceil(3.2);
-- 向下取最大整数
SELECT floor(3.2);
SELECT floor(score),score FROM tb_stu;
-- 取余数
SELECT mod(21,3);
-- 得到 0-1之间的随机值
SELECT rand();
-- 有2位小数的四舍五入值
SELECT round(5.678,2);
-- 截断,小数位保持2位
SELECT TRUNCATE(5.67888,2);

1.4.3.日期函数

日期 时间

  • now() 返回当前的日期+时间

  • curdate()返回系统日期,不包含时间

  • curtime() 返回当前时间,不包含日期

  • year()年 获取指定的年 month() monthname()

-- 当前日期,当前时间,日期和时间
SELECT CURDATE(),CURTIME(),now();
-- 指定日期是一年中的第几周
SELECT WEEK(now());
-- 返回指定日期的年份
SELECT YEAR(now());
-- 返回指定时间的小时
SELECT hour(now()),hour(CURTIME());
-- 返回date的月份名
SELECT MONTHNAME(now());

1.4.4.其他函数

  • version() 版本号

  • user()当前用户

  • if(exp1,exp2,exp3)如果exp1为true,取exp2的值 否则取exp3的值 和三元运算符相似

    SELECT VERSION();
    SELECT USER();
    SELECT DATABASE();
    SELECT IF(10>2,'10','2') a;

1.5.数据库范式

1.5.1.范式

  • 关系型数据库;使用关系模型去组织数据的数据库 称之为关系型数据库 关系模型就是 二维表格;表格与表格之间有关联;

  • 数据库范式其实是一种 规范,规则

  • 第一范式(1NF)用来确保每列的原子性,要求每列(或者每个属性值)都是不可再分的最小数据单元(也称为最小的原子单元)。

  • 第二范式(2NF)在第一范式的基础上更进一层,要求表中的每列都和主键相关,即要求实体的唯一性。如果一个表满足第一范式,并且除了主键以外的其他列全部都依赖于该主键,那么该表满足第二范式。

  • 第三范式(3NF)在第二范式的基础上更进一层,第三范式是确保每列都和主键列直接相关,而不是间接相关,即限制列的冗余性。如果一个关系满足第二范式,并且除了主键以外的其他列都依赖于主键列,列和列之间不存在相互依赖关系,则满足第三范式。

1.5.2.表之间的关系

1,一对多的关系; 例如员工表和部门表,一个部门对应多个员工,所以员工表是多的一方

  • 需要在多的一方 创建外键 和一的一方进行关联

2,多对多的关系;

  • 例如 学生表和课程表(每个学生选多个课程,每个课程有多个学生学习 需要建立第三张表展示这种关系)

  • 例如 用户表和角色表(每个用户有多个角色 每个角色下有多个用户 需要建立第三张表展示这种关系)

  • 需要第三张表,第三张表出现两个外键 分别和两张表的主键关联

3,一对一

  • 一般都合为一张表

数据库存储引擎:在MySQL中的数据使用不同的存储技术存储在文件或内存中

-- 查看MySQL中所用的存储引擎
show engines;

innodb是支持事务的,

而myisam,memory不支持事务

1.6.数据库事务

1.6.1.什么是事务

  • Transaction

  • 事务:一个最小的不可再分的工作单元;通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务就是一个最小的工作单元) sevice transfer(){ dao1.update, dao2.update,dao3.update } 很多个操作

  • 一个完整的业务需要批量的DML(insert、update、delete)语句共同联合完成

  • 事务只和DML语句有关,或者说DML语句才有事务。这个和业务逻辑有关,业务逻辑不同,DML语句的个数不同

1.6.2.事务四大特性ACID

  • 原子性(Atomicity):事务不可分割的最小工作单元,事务内的操作要么全做,要么全不做。事务具有要么全部成功 要么全部失败 这就是原子性。

  • 一致性(Consistency):在事务执行前数据库的数据处于正确的状态,需事务执行完后数据库的数据依然处于正确的状态,即数据完整性约束没有被破坏,如A给B转帐,不论转帐是否成功,转帐之后的A和B的帐户总额和转帐之前是相同的 3000 4000

  • 隔离性(Isolation):当多个事务处于并发访问同一个数据库资源时,事务之间相互影响,不同的隔离级别决定了各个事务对数据资源访问的不同行为

  • 持久性(Durability):事务一旦执行成功,它对数据库的改变是不可逆的

在业务逻辑层,一个service层的某个业务方法可能需要执行多次增删改操作,如果这期间发生了异常,数据库事务不回滚的话 数据库中的数据就会不完整,举个例子,订单信息中包含订单明细,现在在保存订单的业务逻辑方法中,先保存订单成功了,再保存订单明细,如果保存订单明细的过程中失败了,肯定希望之前的保存订单数据回滚。

1.6.3.和事务相关语句

  • 开启事务 start transaction | begin

  • commit:提交

  • rollback:回滚

1.6.4.事务何时开启 何时结束

开始与结束

开始标志:Mysql默认情况下 任何一条DML语句(insert、update、delete)执行,标志事务的开启

结束标志:

  • 提交:成功的结束,将所有的DML语句操作历史记录和底层硬盘数据来一次同步

  • 回滚:失败的结束,将所有的DML语句操作历史记录全部清空

何时提交

在MySQL中,默认情况下,事务是自动提交的,也就是说,只要执行一条DML语句就开启了事务,并且提交了事务。自动提交机制是可以关闭的,可以由程序控制何时提交。

1.6.5.事务和底层数据库的关系

在事务进行过程中,未结束之前,DML语句是不会更改底层数据,只是将历史操作记录一下,在内存中完成记录。只有在事务结束的时候,而且是成功的结束的时候,才会修改底层硬盘文件中的数据。如果执行失败,则清空内存中所有的历史操作记录,不会对底层硬盘文件中(数据表)数据做任何修改。

-- 开启事务
START TRANSACTION;
INSERT into tb_stu(sid,sname) VALUES(5,'jerry'); 
-- rollback 的执行不会更新 磁盘文件
-- commit是事务执行成功 提交 
COMMIT;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值