MySQL

MySQL

前言:

Java后端 第一步 认识SQL

1.认识SQL

1.1mysql 启动方法

mysql 环境变量配置正确后,要使用管理员身份启动 cmd

cmd1 :

net start mysql
service mysql restart

cmd2 :

mysql -u root -p
mysql -u root -p****** --或者直接输入密码

cmd3 : pwd = mysql_native_password

更改环境变量后配置MySQL

  1. 把当前MySQL目录\bin添加到系统变量,非用户变量

  2. 进入mysql基础目录,修改 my.ini 文件,base,data目录均修改,可以不跳过密码检查

  3. 管理员模式进入cmd,\bin目录下 mysqld -install

    MySQL

  4. \bin目录下 net start mysql

MySQL

5.mysql -uroot -p**

可能需要重复配置比较费力,不建议改变原始路径

1.2 sql 基本语句


1.2.1基本操作
sc delete mysql    --删除所有配置 慎用

create database xxx ; --创建一个数据库

drop database xxxxx ; --删除数据库的所有内容,包括原数据库

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

use xxxxxx; --切换xxxxxx数据库

show tables; --查看数据库中所有的表

describe xxx ; --查看xxxxxx数据库中xxx表单的信息

sqlyog operations : 选中ctrl+a---执行语句 左上角按钮执行

飘号引用 sqlName.tableName

1.2.2创建表单 主键必须非空
CREATE TABLE `school`.`techer` ( `id` INT(10) NOT NULL COMMENT '教职工号', `name` VARCHAR(10) COMMENT '姓名', `age` INT(3) COMMENT '年龄', PRIMARY KEY (`id`) ) ENGINE=INNODB CHARSET=utf8 COLLATE=utf8_general_ci; 

----初始化一个数据库的表形状

学习sql语法妙招:先用GUI 然后看GUI操作后的sql语句

1.3 sql基本数据类型

sql数值类型

tinyint   1 bit
smallint  2 bit 
mediumint 3 bit
int       4 bit   
bigint    8 bit
float     8 bit
decimal	  字符型串浮点数 精确,精确,商用

sql字符串类型

char 				0~255
varchar 可变字符 	0~65535 
tinytext 			2^8-1
text 				2^16-1

sql时间日期

date YYYY-MM-DD 
time HH:mm:ss
datetime YYYY-MMM-DD HH:mm:ss 
timestamp 1970.1.1-now 
year

sql null

无值 null 运算 null

1.4 sql字段属性

MySQL

 

Unsigned :

  • 无符号整数
  • 声明非负

zerofill :

  • 不足的位数用0补全到 限定位数 eg.INT(10) 1->0000000001

自增

  • 自动在上一条记录上+1
  • 唯一的主键 index 要子增 整数类型

非空 :

NULL

NOT NULL :如果不赋值 报错

1.5 sql表单语句

show create database school  --查看创建数据库语句
show create table student --查看 student 数据表的定义语句
desc student --显示表的结构

1.6 sql 中ENGINE INNODB和MYISAM 的区别

  MYISAM INNODB
事务支持 不支持 支持
数据行锁定 不支持 (表锁) 支持 (行锁)
外键约束 不支持 支持
全文索引 支持 不支持
表空间的大小 较小 较大 ,约为2倍
常规使用操作 节约空间 ,速度较快 安全性高,事务处理,多表多用户操作
物理文件上 *.frm --表结构的定义文件 ; *.MYD数据文件(data) ; *.MYI 索引文件 (index) 在数据库表中只有一个*.frm文件,以及上级目录下的ibdata1 文件

物理空间的存储位置 :

所有的数据库文件都存在data目录下

设置数据库表中的字符集编码

CHARSET=utf8

不设置的情况,会是mysql默认的字符集编码 (不支持中文)

MySQL 的默认编码是 Latin1

在my.ini 中配置 默认的编码

character-set-server=utf8

1.7 sql的表单修改 (修改范式)

1.7.1表单内操作

改名规则 :

ALTER TABLE 旧表名 RENAME AS 新表名

添加规则 :

ALTER TABLE 表名 ADD 字段名 列属性 [属性]

修改规则 :

ALTER TABLE 表名 MODIFY 字段名 列属性[属性]
ALTER TABLE 表名 CHANGE 旧字段名 新字段名 列属性[属性]

删除规则(删除列) :

ALTER TABLE 表名 DROP 字段名

修改主键

ALTER TABLE Skills DELETE PRIMARY KEY
ALTER TABLE Skills ADD PRIMARY KEY ( SkillID, SkillName );

添加外键

alter table user add key `outside_KEY` (`id`);

1.7.2 表单整体操作

整体删除

DROP TABLE IF EXISTS `XXX`

其他语法规则

( ` )单反号 (飘号) 用来 标识 库名;表名;字段名;索引;别名

一个DATABASE 有一个 db.opt 来保存当前的options 选项表

注释 # ;/* */ ;--;

SQL大小写不敏感

2.MySQL数据管理

2.1 外键

2.1.1 创建表时候直接添加外键

建表 grade

CREATE TABLE `grade`(
 `gradeID` INT(10) NOT NULL  AUTO_INCREMENT COMMENT '年级号',
 `gradeName` VARCHAR(20) NOT NULL DEFAULT 'name' COMMENT '年级名',
  PRIMARY KEY (`gradeID`)
)ENGINE=INNODB DEFAULT CHARSET=utf8

建表 student 并添加外键

CREATE TABLE IF NOT EXISTS `student` (
`id` INT(10) NOT NULL AUTO_INCREMENT COMMENT '学生学号' ,
`otherInformation` VARCHAR(50) NOT NULL DEFAULT 'info' COMMENT '其他信息' ,
`gradeID` INT(10) NOT NULL COMMENT '学生的年级',
PRIMARY KEY (`id`) ,--主键
KEY `FK_gradeID` (`gradeID`), --添加外键
CONSTRAINT  `FK_gradeID` FOREIGN KEY (`gradeID`)  REFERENCES `grade`(`gradeID`)  --添加约束
)ENGINE =INNODB CHARSET=utf8

逻辑关系 :

MySQL

grade 不可被直接删除 由于student 定义了对于grade 的外部键

删除有外键的表 ,不可直接删除依赖的表

2.1.2 创建表后添加外键

ALTER TABLE `student`  --修改表名
ADD CONSTRAINT `FK_gradeID` FOREIGN KEY (`gradeID`)  REFERENCES `grade` (`gradeID`) --添加约束 增加外键字段的位置

不用外键 :

阿里内部(业界)强制规范 :不得使用外键与内部相关联 ,一切外键概念必须再应用层解决

2.2 DML语言 (修改数据)

数据库的意义 :大规模数据存储 建议全文背诵

2.2.1 添加

插入单个字段

INSERT INTO `grade` VALUES(content) -- 内容和列数据 一一匹配

插入多个字段

INSERT INTO `grade` (`gradeName`) --形容 表.列
VALUES('大四') ,('研一'); --值
INSERT INTO `student` VALUES(1,'info1',1),(2,'info2',2); --外键值 必须对应于索引中的匹配

2.2.2修改

uodate 修改 (状态)

修改一个属性

UPDATE `student` set `name`='狂神' WHERE id=1;

修改多个属性 , 逗号隔开

UPDATE `student` SET `name`='老八',`age`= 35 ,`otherInformation`='老八蜜汁小憨包' WHERE id=2;

 

WHERE 附加运算符

操作符 含义 范围
= 等于 绝对满足条件
<> 或者 != 不等于 绝对不满足
> 大于 绝对大于
< 小于 绝对小于
<= 小于等于 。。
>= 大于等于 。。
BETWEEN ...and... 范围 范围与
AND 条件与
OR 条件或

2.2.3 删除

删除单条数据

DELETE FROM `student` WHERE id=9;

清空表单 (不建议使用)

DELETE FROM `student`

建议使用的清空数据库操作

TRUNCATE `student`

二者的相同点:都能删数据 都不会删除表单结构

区别:

  • TRUNCATE 重新设置 ,自增列 计数器会归零
  • TRUNCATE 不会影响事务,索引从一开始
  • DELETE 影响事务 ,新索引设置为上次删除的最后一位加一

而且DELETE删除后 重启数据库 的现象

引擎 问题
INNODB 自增列从一开始 (存储在内存中,断电即失)
MYISAM 自增从上一个自增开始(存在文件中 断电不失)

2.2.4刷新数据库

flush privileges

2.2.5 DML小结

INSERT INTO `student` VALUES(5,'网银',3,'老铁',30,CURRENT_TIME); --严格按列 否则失败
UPDATE `student` SET `name`='王银' ,age=18 WHERE id=5; 
DELETE FROM `student` WHERE id=5;

SELECT

3.DQL查询数据

3.1 认识DQL

3.1.1重要性

  • Data QUERY LANGUAGE : 数据查询语言

  • 支持所有类型的查询

  • SQL最核心的语言规范

  • SQL使用频率最高的语言规范

    3.1.2 SELECT完整语法

    SELECT [ALL | DISTINCT]
    {* | TABLE.* | [TABLE.field1][AS alias1],[TABLE.field2][AS alias2] ,...}
    FROM `tableName` as [TABLE_alias]
    [LEFT | RIGHT | INNER JOIN table_name] -- 联表查询
    [WHERE ... ] -- 指定结果满足条件
    [GROUP BY ... ] -- 指定结果按照字段分组
    [HAVING] -- 过滤分组的记录必须满足的次要条件
    [ORDER BY ... ] -- 指定查询记录按一个或者多个排序
    [LIMIT {[OFFSET]ROW_COUNT | ROW_COUNTOFFSET OFFSET}];
    -- 指定查询的记录从那条至哪条
    

     

3.2 查询

3.2.1 基本查询操作

1.查询表的所有数据

SELECT * FROM student; --不带飘号 
SELECT * FROM `grade`; --带飘号  

2.查询指定字段

SELECT `gradeName` FROM grade ; 
SELECT `name` ,`age` FROM student; 

3.查询指定字段,指定别名

SELECT `name` AS 学生姓名,`age` AS 学生年龄 FROM student;

3.2.2 DQL函数

1.连接函数

SELECT CONCAT ('姓名 : ',`name`) AS 标准名 FROM `student`;

3.2.3 普通的查询操作

1.去重操作

SELECT DISTINCT `name` FROM `student` ;

2.所有数据 +1

SELECT `totalScore`+1 FROM `student`; 

注意:只是显示出来的数据+1 不会改变原表的内容

3.2.4 DQL (SELECT)的其他功能

1.查询SQL版本号

SELECT VERSION()

2.计算表达式的结果

SELECT 100*3-1 AS

3.查询自增步长

SELECT @@auto_insrement_increment 

3.3 进阶查询

3.3.1where条件子句

作用 : 检索数据中的符合条件的值

运算符 语法 描述
AND && a AND b a&&b 逻辑与
OR || a OR b a||b 逻辑或
Not ! NOT a ! a 逻辑非

对于区间查询的三种写法

  1. &&
SELECT studentNo ,studentRes FROM result WHERE studentRes >=80 && studentRes <=95;
  1. BETWEEN AND
SELECT studentNo ,studentRes FROM result WHERE studentRes BETWEEN 80 AND 95;
  1. AND
SELECT studentNo ,studentRes FROM result WHERE studentRes >=80 AND studentRes <=95;

或 ,非 操作类似 不多冗述

3.3.2模糊查询

本质 : 比较运算符

运算符 语法 描述
IS NULL a is null NULL为真
IS NOT NULL a is not null 不是NULL 为真
BETWEEN a between b and c a 在 b c间 为真
Like a like b SQL匹配 a 匹配b 为真
in a in (a1,a2,a3....) a在给定数组字段中为真

查询通配符 :

% 匹配任何数量的任意字符

SELECT studentRes FROM result where studentName Like '刘%'
-- 可以匹配如刘洋 刘建伟 刘行赵丽 刘大苏打大大啊sdadasa 
-- 匹配名字中有 嘉的 Like '%嘉%'

_ 匹配一个任意字符

SELECT studentRes FROM result where studentName Like '刘_'
-- 可以匹配如 刘洋 刘备 刘兵 刘申 
-- '刘__'匹配两个任意字符
-- '刘___'匹配三个任意字符 以此类推....

3.4 JOINON联表查询

3.4.1七种理论

MySQL

 

3.4.2三个例子

3examples :

1.INNER JOIN 相交查询

SELECT s.gradeID ,s.`name` -- 查询内容
FROM `student` AS s        -- 起别名
INNER JOIN `grade` AS g    -- 内联查询
WHERE s.gradeID=g.gradeID; -- 条件

2.Right JOIN 即使左表没有匹配也会从右表返回所有的值 以右表为基准

SELECT s.gradeID,s.name
FROM `student` AS s -- 左表
RIGHT JOIN `grade` AS g -- 右表  
ON s.gradeID=g.gradeID; 

3.Left JOIN 即使右表没有匹配也会返回左表的所有值 以左表为基准

SELECT s.gradeID,s.name
FROM `student` AS s   -- 左表
LEFT JOIN `grade` AS g -- 右表
ON s.gradeID=g.gradeID; 

语句思路:

1.分析需求 ,分析查询的字段来自哪些表 student result subject (连接查询)

2.确定使用哪种的连接查询

3.判断交叉点 :相同的数据

4.判断交叉条件:WHERE 子句

注意:

ON 连接查询

WHERE 条件查询

 

3.4.3多表查询

SELECT s.gradeID,s.name ,sc.totalScore  -- student的年级 学生姓名 总分
FROM student AS s -- 
LEFT JOIN grade AS g 
ON s.gradeID=g.gradeID
RIGHT JOIN score AS sc
ON sc.id=s.gradeID;

3.5 自查询,自连接

自己和自己连接

把一张表拆成两张表

复习:

1.建表

CREATE TABLE IF NOT EXISTS`school`.`学习清单`(
`pid` INT(10) NOT NULL DEFAULT 1 COMMENT '父亲id',
`selfid` INT(10) NOT NULL DEFAULT 2 COMMENT '自己id',
`content` VARCHAR(20) COMMENT '内容',
PRIMARY KEY (`selfid`)
)ENGINE=INNODB CHARSET=utf8 COLLATE=utf8_general_ci;

2.插值

INSERT INTO `学习清单`
VALUES(1,1,'软件开发'),(2,2,'人工智能'),
(1,3,'Java编程思想'),(1,4,'编译原理'),
(2,5,'机器学习'),(2,6,'数据挖掘');

3.自连接,自分区

SELECT a.`content` AS `父类`,b.`content` AS `子类`
FROM `学习清单` AS a,`学习清单` AS b
WHERE a.`selfid`=b.`pid`;

结果:

MySQL

定义自己的父亲是自己 ,讲一个父类分为几个子类的过程

修改后

UPDATE `学习清单` SET `pid`=0 WHERE content='软件开发' OR content='人工智能';

MySQL

3.6 分页和排序

起始页下标 [i ,pagesize] 容纳量 (i-1)*pagesize

SELECT a.`content` AS `父类` ,b.`content` AS `子类`
FROM `学习清单` AS a ,`学习清单` AS b
WHERE b.pid=a.selfid
ORDER BY `父类` ASC 
LIMIT 0,6;

limit 语法:

limit 查询起始下标 pageSize

排序 语法 :

ORDER BY `key` ASC  -- 升序
ORDER BY `KEY` DESC -- 降序

3.7.子查询 (嵌套查询)

where 语句中再嵌套一个 select 语句

1.原始方法 : 联表查询方法

SELECT s.otherInformation AS `爱好`,s.id AS `身份号码`,sc.totalScore AS `总分`
FROM `student` AS s
INNER JOIN `score` AS sc
ON s.id=sc.id
ORDER BY sc.totalScore DESC

2.新方法 : 子查询(嵌套where方法) 子查询不能多于一行

SELECT DISTINCT s.otherInformation AS `爱好`,s.id AS `身份号码`,s.`name` -- DISTINCT 去重 
FROM `student` AS s 
WHERE s.id IN (
	SELECT id FROM `score` WHERE `totalScore` BETWEEN 600 AND 700  -- where in 查询范围
)
ORDER BY s.id ASC ;

3.8 SELECT小结

某宝,某东,某夕夕千人千面

不仅是 mysql 还有Redis ,cloud ,SequoialDB 等非关系/缓存储型,比较复杂

4.MySQL函数

具体请参考官网文档 : https://dev.mysql.com/doc/refman/5.7/en/introduction.html 用的话直接查找即可

4.1常用函数

SELECT 为先 永远SELECT

ABS()|CEILING()|FLOOR()|RAND()|SIGN() .....都是见名知意的

4.2聚合函数

函数名 描述
COUNT() 计数
SUM() 求和
AVG() 平均值
MAX() 最大值
MIN() 最小值
... ...

忽略所有的NULL值

select count(name) from `student`

select * 1 null的辨析 请上网参考各路博文和官方DOC 只有纳百家之长 才能清晰理解,这里不粘链接

4.3DQL查询分组

eg. 查找一个科目的 平均,最大,最小分,并分类统计

SELECT  s.name AS `姓名`,s.age AS `年龄`,AVG(`高等数学`) AS `平均分` ,MAX(`高等数学`) AS `最高分`, MIN(`高等数学`) `最低分`
FROM `score` AS sc
INNER JOIN student AS s
ON s.id=sc.id 
GROUP BY s.id

4.4数据库级别的MD5查询加密

4.4.1定义

来自baidu :

MD5信息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。MD5由美国密码学家罗纳德·李维斯特(Ronald Linn Rivest)设计,于1992年公开,用以取代MD4算法。这套算法的程序在 RFC 1321 标准中被加以规范。1996年后该算法被证实存在弱点,可以被加以破解,对于需要高度安全性的数据,专家一般建议改用其他算法,如SHA-2。2004年,证实MD5算法无法防止碰撞(collision),因此不适用于安全性认证,如SSL公开密钥认证或是数字签名等用途。

 

4.4.2加密代码(mysql实现)

1.建表

CREATE TABLE `testmd5`(
`id` INT(4) NOT NULL ,
`name` VARCHAR(20) NOT NULL ,
`pwd` VARCHAR (50) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE =INNODB DEFAULT CHARSET=utf8;

2.插值

INSERT INTO `testmd5` VALUES (1,'zhangsan','123456'),(2,'wangwei','123456'),(3,'lisi','1233456');

3.MD5方式加密

UPDATE testmd5 SET pwd=MD5(pwd)

或者在插入时就加密

INSERT INTO `testmd5` VALUES (4,'sange',MD5('pop3'));

4.检验用户传过来的密码正确性

select * from testmd5 where `name`='sange' and pwd=md5('pop3')

5.事务和业务

5.1什么是事务

要么都成功,要么都失败

eg1.定义某个事务为 : A给B转账 x元,保证A 拥有大于等于x元.

事务成功为 : A的账户记录减少x元 ,并且B的账户记录增加x元 ,两者必须都成功 才事务成功,否则事务失败


SQL执行事务 抽象逻辑 A账户状态 B账户状态 总和
* 初始状态 1000 1000 2000
A记录 - 200 A给B转账200 800 1000 2000
B记录 + 200 B收到A的200 800 1200 2000
* 结束状态 800 1200 2000

绝对满足表格,事务成功 Transaction success

5.2ACID原则


事务原则 : ACID 原则 原子性,一致性,隔离性,持久性

1.原子性 Atomicity

原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生

2.一致性 Consistency

事务前后数据的完整性必须保持一致

3 隔离性 Isolation

事物的隔离是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他的事务的操作数据干扰,多个并发事务之间要相互隔离

4.持久性 Durability

持久性是一个事务一旦被提交,他对数据库中的数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

 

隔离产生的一些问题

脏读:

指一个事务读取了另外一个事务未提交的数据

不可重复读

在一个事务内读取表中的某一行数据 多次读取结果不同 (非错误,是场合不对)

虚读幻读):

是指在一个事务内读取到了别的事务插入的数据 导致前后读取不一致

5.3测试事务

5.3.1 内容

  1. 设置事务自动提交到数据库的状态
SET autocommit=0; -- 设置事务 关闭 
SET autocommit=1; -- 设置事务 开启(默认)

 

2.手动处理事务

标记一个事务的开始,从此时起sql都在同一个事务内

set autocommit=0;

start transaction

增加事务记录

insert xxx

提交

commit 

事务失败 ,回滚

ROLLBACK

事务结束 回复到默认状态

set autocommit=1;

注 :

保存点 :设置一个事务的保存点

SAVEPOINT 

回滚到保存点

rollback to savepoint

撤销保存点

release savepoint

事务逻辑图 :原创

MySQL

5.3.2事务实现

只有代码

转账事务实现

一次执行一条,这很重要

CREATE DATABASE  IF NOT EXISTS `shop` ;

USE shop;

CREATE TABLE IF NOT EXISTS account(
id INT(10) NOT NULL AUTO_INCREMENT COMMENT ‘账户名‘,
name VARCHAR(10) NOT NULL COMMENT ‘姓名‘,
money DECIMAL(9,4) NOT NULL COMMENT ‘账户金额‘,
PRIMARY KEY (id)
)ENGINE=INNODB CHARSET=utf8 COLLATE=utf8_general_ci

INSERT INTO account VALUES(1,‘Roky‘,1000.00),(2,‘Jane‘,5000.00),(3,‘Pony‘,10000.00);

SET autocommit=0;

START TRANSACTION

UPDATE account SET money=money-200 WHERE name=‘Jane‘
UPDATE account SET money=money+200 WHERE name=‘Roky‘

COMMIT
ROLLBACK

SET autocommit=1;

 

6.索引原理

推荐博客:https://blog.codinglabs.org/articles/theory-of-mysql-index.html

从操作系统,计算机底层架构和数据结构,算法讲解的索引原理。是一篇质量极其高的博文,博主写了半个月,成文时间2011年,年代较远,但没有影响它的价值,个人看了3天。顺便说两句,从计算机底层总结的东西,都值得我们仔细钻研;程序不仅仅是事务逻辑和框架,从来都是数据结构算法,不懂底层原理,只能成为附庸

6.1 阅读博文和官方Doc 心得笔记

1.索引本质

我们想更加快速的找到数据,我们都知道mysql是根据索引查找数据,但是普通的查找可能不会高效,依靠数据结构才能更加高效,所以所谓索引是一种数据结构

2.为什么选择数据结构

解决海量用户对于海量数据的高并发问题

3.MySQL选择的数据结构

我们已经知道 BST 在查找方面的性能非常优越,但会造成退化,AVL和 R-B这两个变种对于退化做了一些优化,R-B相对于AVL来说Rotate没那么多,增加了结点的parent和color,已经非常优越了,于是,Java的HashMap选择了这种结构,但是MySQL并没有选择这两种,而是更为复杂的 B-Tree 和 B+Tree ,MySQL和HashMap都是以Key-Value方式查找Value。而HashMap是程序运行时有效的,非持久化,就是在RAM中断电即失,而MySQL是持久性的,存储在磁盘的分区,说白了,HashMap性能再高,存储的数据也要依靠内存大小,而MySQL是廉价的硬盘,数据量大到几百亿还可以运行。在Sahni博士所著作的数据结构与算法 树的末尾章节有详细讲述B-树的原理,但是没有代码描述,总体来说,这种结构相对复杂.

2.1 B- /B+树 概括结构

一切树的本质 : 对于用链表描述的结构来讲永远是递归的.

一些定义

根节点 :根

内部节点 : 非空非根的结点

外部结点:叶子节点的儿子节点 ,就是NULL

抽象结构:一个B-树 是一个m叉搜索树,可以理解为有序数组和树形的结合。

结点概况:一个节点数为m的B树可以有[m/2,m]个,这个结点是一个长度为m的数组,这个数组是有绝对不降序的,(绝对不降序是指对于数组的整体元素来讲,可以有相同的元素,但是MySQL不允许这种情况)对于内部的结点来讲,根节点数组长度至少为2,所有的外部节点都在同一个层,保证了树高h可以绝对一致化

排列顺序:一个结点的数组最头部结点的孩子结点的Key都小于该节点,一个结点数组尾部结点Key都大于该节点,一个结点数组中第i个元素Key 大于他的第i子Key,小于他的第i+1子的Key。

查找方式:所以我们在查找一个元素时候,先在根节点中间比较,找到适合的区间,这个过程是二分,对于合适区间进行跳跃,这个过程是树形.

B+树的优化:B+树对于 原结点的数组做了优化,每个结点增加了 一个指向下一个元素的指针,这个可以优化WHERE语句的区间查阅行为。

3.底层原理

对于计算机底层原理不敢多说,笔者是大一小白一枚,计算机导论有讲述,不过涉及过少,因为竞赛和做项目原因提前学习MySQL.

 

6.2 索引分类

在一个表中主键索引只有一个 ,唯一索引可以有多个

  • 主键索引 PRIMARY KEY

    • 唯一标识,主键不可重复,只能有一个列作为主键索引
  • 唯一索引 UNIQUE KEY

    • 避免重复的列出现,唯一索引可以重复 ,多个都可以标识位 唯一索引
  • 常规索引 KEY/INDEX

    • 默认的
  • 全文索引 FULLTEXT

    • 在特定的数据库引擎下才有 (MyISAM)

 

索引的添加方式

  • 创建表初期,给索引增加字段 ,在字段后面添加 xxx KEY (xxx字段)
  • 创建完毕,增加索引 ALTER TABLE xxx ADD xxx KEY xxx (xxx)

 

显示索引信息

SHOW INDEX FROM `account`

增加全文索引

ALTER TABLE `shop`.`account` ADD FULLTEXT INDEX `fullindex` (`name`) 

分析 sql 的执行情况

EXPLAIN SELECT * FROM `account`
SELECT * FROM `account` WHERE MATCH(`name`) AGAINST('Pony');

mysql之explain相关博文 :

https://blog.csdn.net/jiadajing267/article/details/81269067

6.3 测试百万级数据量

MySQL 不仅存储数据,增删改查 而且是可以编程的

6.3.1插入随机的百万数据

定义函数

DELIMITER $$

CREATE FUNCTION analog()
RETURNS INT
BEGIN
DECLARE num INT DEFAULT 1000000;
DECLARE i INT DEFAULT 0;
WHILE i<num DO
INSERT INTO app_user (name,email,phone,gender,password,age)VALUES(CONCAT(‘用户‘,i),CONCAT(FLOOR(RAND()(9999999-1000000)+1000000),‘@qq.com‘),CONCAT(‘18‘,FLOOR(RAND()((999999999-10000000)+10000000))),FLOOR(RAND()2),UUID(),FLOOR(RAND()100));
SET i=i+1;
END WHILE;
RETURN i;
END;

执行函数

SELECT analog()

6.3.2测试查询

测试

SELECT * FROM `app_user` WHERE `name`='用户9999'

解释

explain SELECT * FROM `app_user` WHERE `name`='用户9999'

我们给名字添加普通索引试一下

CREATE INDEX id_app_user_name ON app_user(`name`)

添加索引耗费时间10~15s左右

MySQL

可以看到时间和效率大大提升了

MySQL

 

查询时间由2.718 sec ->0.001 sec

查询列数由 992787 row -> 1 row

这在解决高并发问题上很有效的

6.4添加索引的原则

  • 索引不是越多越好,多则繁琐,你也记不住
  • 不要对进程变动数据加索引,一致性
  • 小数据量的表不需要索引,画蛇添足,多此一举
  • 索引一般加在经常常用来查询的字段上

7.权限管理与数据库备份

权限管理的目的:

在公司中,一个业务或服务有一个数据库,这个数据库管理员享有最高的权限,而普通员工只有一般权限,不可能所有人都最高权限,不然你删库跑路怎么办

7.1 SQLYog可视化管理

无脑点击左上角即可

7.2 SQL命令管理

1.创建用户

create user juminiy identified by '123456' -- pwd

2.修改密码

当前用户

set password =password('123456')

其他用户

set password for juminiy =password('123456')

重命名用户

rename user juminiy to kkk03

授权 对于某个用户的全部权限

grant all privileges on *.* to juminiy

但是不能给别人授权, root可以,唯一的和ROOT不同处就是GRANT

查看权限

show grant for juminiy

查看root权限

show grant for root@localhost

撤销权限

revoke all privileges on *.* from juminiy  

删除用户

drop user juminiy

7.3 SQL备份

1.为什么备份 :

  • 保证重要的数据不丢失
  • 数据的转移

2.MySQL数据库备份的方式

  • 直接拷贝

  • 可视化工具手动导出

  • 命令行导出 mysqldump 命令行使用

     

    数据库导出

先 net start mysql

直接在 cmd 或者 bash上操作即可

# mysqldump -h 主机 -u 用户名 -p 密码 数据库 表1,表2,表3 > 物理磁盘的位置 /文件名
mysqldump -hlocalhost -uroot -p123456 school student >D:/a.sql

数据库导入

-- 先登录数据库
mysql -uroot -p123456
-- 执行导入
source d:/a.sql
-- 不登录数据库
mysql -uroot -pxxxxxx 库<备份文件

保证这个数据库名存在,数据库存在,才能导入成功

 

8.数据库的规约,三大范式

8.1 为什么需要数据规范化?

  • 信息重复

  • 更新异常

  • 删除异常

    • 无法正常删除信息
  • 插入异常

    • 无法正常显示信息

 

8.2 三大范式 :

8.2.1 第一范式 1NF:

原子性:保证每一列不可分

8.2.2 第二范式 2NF:

前提:满足1NF

每张表只描述一件事务

8.2.3 第三范式 3NF:

前提:满足 2NF

第三范式需要确保数据表中的每一列数据都PRIMARY KEY直接相关,不能间接相关

那么在实际的应用中呢,范式虽然是范式,但是是有问题的,有时候为了性能,可以不满足1NF 2NF 3NF

8.4 规范性和性能的问题

阿里规约:关联查询的表不可超过三张

  • 考虑商业化的需求和目标 (成本,用户体验)数据库的性能更重要
  • 在规范性能的问题的时候,需要适当放的考虑一下规范性
  • 故意给某些表增加一些冗余的字段 (从多表联查变为单表查询)
  • 故意增加一些计算列 (从大数据量降低为小数据量的查询)

9.JDBC

Java操作数据库

9.1 数据库驱动

驱动:声卡,显卡,数据库

eg.数据库需要驱动程序才能运行

9.2JDBC

SUN公司为了简化开发人员的(对数据库统一的)操作,提供了一个(Java)操作,按照具体的规范去做

导入依赖的包

java.sql

javax.sql

需要的jar包,不然加载不了

9.3 java操作数据库

1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
2.用户信息和URL

mysql版本

String url="jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&useSSL=false";
String name="root";
String password="123456";

oracle版本

String url="jdbc:oracle:thin@localhost1521:sid";
3.连接
Connection c=DriverManager.getConnection(url,name,password);
4.SQL的对象:操作SQL

和mySQL操作相同,见名知意

c.rollback();
c.commit();
c.setAutoCommit(false);
5.执行SQL的对象:执行SQL

和SQL操作相同,也是见名知意的

Statement s=c.createStatement();
s.executeQuery();
s.execute();
s.executeUpdate();
6.获得结果集

不知道什么类型就用Object就可了

ResultSet rs=s.executeQuery(s1);
rs.getObject();
7.释放连接
rs.close();
s.close();
c.close();

9.4 SQL注入

使用statement对象(不安全的)用java操作数据库

jdbc中的statement对象用于向数据库发送SQL语句,想完成对于数据库的增删改查,只需要通过这个对象向数据库发送增删改查的信号即可。

Statement对象的executeUpdate 方法,用于向数据库发送增,删,改,查的SQL语句,executeUpdate执行完成后,将会返回一个整数(告知我们几行发生变化,提示信息和SQL相同)

1.预备工作:封装一个工具类

public class sqlIn {
 private Connection c;
 private Statement s;
 private ResultSet rs;
 public void drive() throws ClassNotFoundException, SQLException {
     Class.forName("com.mysql.jdbc.Driver");
     String url="jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&useSSL=false";
     String name="root";
     String password="123456";
     c= DriverManager.getConnection(url,name,password);
     s=c.createStatement();
 }
 public void login(String name,String pwd) throws SQLException {
     String opr="select * from `login` where `name`='"+name+"' and password='"+pwd+"'";
     rs=s.executeQuery(opr);
     while(rs.next()){
         System.out.println(rs.getObject("name"));
         System.out.println(rs.getObject("password"));
     }
 }
}

2.正常查询

public static void main(String[] args) throws SQLException, ClassNotFoundException {
     sqlIn p=new sqlIn();
     p.drive();
     p.login("Tom","123456");
 }

3.SQL注入

欺骗服务器的规范

sql存在漏洞 ,违法的字符串拼接

select * from `tableName` where `rowName1`=' 'or 1=1' `rowName2`=' 'or 1=1'

代码实现

public static void main(String[] args) throws SQLException, ClassNotFoundException {
     sqlIn p=new sqlIn();
     p.drive();
     p.login(  " 'or '1=1"  ,   " 'or '1=1"  );
 }

 

9.5 安全的对象

java一个专门防止SQL注入的类: PreparedStatement

接上边的9.4的类

java操作数据库

1.添加数据

public void insert(int id,String name,String pwd) throws SQLException {
   String opr="insert into login(`id`,`name`,`password`) values(?,?,?)";
   ps=c.prepareStatement(opr);//c->connection 对象
   ps.setInt(1,id);
   ps.setString(2,name);
   ps.setString(3,pwd);
   ps.executeUpdate();//执行更新 否则无效
}
public static void main(){
p.insert(13,"ppd1234","91881qq");插入
}

2.删除数据

public void delete(int id) throws SQLException {
   String opr="delete from `login` where id="+Integer.valueOf(id);
   ps=c.prepareStatement(opr);
   ps.executeUpdate();
}
public static void main(String args[]){
p.delete(1);
}

3.更新数据和查找数据不多解释,opr字符串就是SQL中的操作,Java执行excuteUpdate()就能成功

 

9.6使用IDEA连接数据库

Community版本:右边栏

Education版本:https://blog.csdn.net/cnds123321/article/details/102854508

踩了好多坑才连接上 呜呜呜///

 

9.7 Java执行事务

java操作事务和SQL操作事务是一样的同样遵循ACID原则

如果不了解什么是事务 请回到 5事务和业务章节学习

eg.用户转账

public void accountPay(String fromAccount,String toAccount,int Money) throws SQLException {
   try{
       c.setAutoCommit(false);
       StringBuilder sb1=new StringBuilder();
       sb1.append("update account set money=money-").append(Integer.valueOf(Money).toString()).append(" where `name`= '").append(fromAccount).append("'");
       ps=c.prepareStatement(sb1.toString());
       ps.executeUpdate();
       StringBuilder sb2=new StringBuilder();
       sb2.append("update account set money=money+").append(Integer.valueOf(Money).toString()).append(" where `name` = '").append(toAccount).append("'");
       ps=c.prepareStatement(sb2.toString());
       ps.executeUpdate();
   }catch (SQLException e1){
       try{
           c.rollback();//失败了 先回滚 钱不能没 ...
       }catch(SQLException e2){
           e1.printStackTrace();
           e2.printStackTrace();
       }
   }finally{
       c.setAutoCommit(true);
       System.out.println("Successful!");
   }
public static void main(String args[]){
p.accountPay("Weiwei","Liping",500);
}

 

9.8 数据库连接

数据库连接--执行完毕--释放

连接--释放 十分的浪费资源

通俗解释:就是你去银行,只有一个服务员,你进去,为你服务,你出去了,银行关闭,下一个人再进来,在连接,服务完,再关闭。而连接池的作用就是设置多个服务员,每个服务员都在等待,银行不会关闭。

可以用别人写好的,例如:DBCP,C3P0,Tomcat ,Druld:Alibaba

也可以自己用java手动实现一个(DataSource)接口

导入依赖:

DBCP :

commons-dbcp2-2.7.0.jar

commons-pool2-2.8.0.jar

使用封装的工具类,测试代码和原来的没有任何的区别

10.基础完结散花,撒花,撒欢,撒欢儿

 

 

 

 

 

MySQL

上一篇:DotNet Core 3.1 EF Core 数据库迁移(Migration)


下一篇:解密PDF文件限制编辑