MySQL基础笔记整理

初识MySql

1.1 为什么学习数据库

  1. 岗位需求

  2. 大数据时代

  3. 被迫需求:存数据

  4. 数据库是所有软件体系中最核心的存在 DBA

1.2 什么是数据库

数据库(DB,Database)

概念:数据仓库,软件,安装在操作系统(window,linux,mac...)之上

作用:存储数据,,管理数据

1.3 数据库分类

关系型数据库:(SQL)

  • MySQL,Oracal,SqlServer,DB2,SQLlite

  • 通过表和表之间,行列之间的关系进行数据库存储,学员信息表,考勤表,...

非关系型数据库:(NOSQL)Not Only

  • Redis,MongDB

  • 非关系型数据库,对象存储,通过对象的自身的属性来决定

DBMS(数据库管理系统)

  • 数据库的管理软件,科学的管理我们的数据,维护和获取数据

  • Mysql是一个关系型数据库管理系统

  • 前世:瑞典MySQL AB公司

  • 今生:Oracle 旗下产品

  • MYSQL是最好的RDBMS(关系数据库管理系统)应用软件之一

  • 开源的数据库软件,体积小,速度快,总体拥有成本低,

创建数据库

新建连接

image-20200427210540834

新建数据库

image-20200427210200661

创建表

image-20200427214352536

查看表

image-20200427215331721

命令行连接数据库

 C:\Users\16225>mysql -uroot -p123456  --连接数据库
 mysql>
 update mysq1.user set authenticati on_string=password('123456') where user= 'root and Host ='localhost'; --修改用户密码
 flush privileges; --刷新权限
 ----------------------------------
 --所有软件都必须使用;结尾
 mysql> show databases; --查看数据库
 mysql> use school --使用数据库
 mysql> show tables; --查看数据库中表
 mysql> describe student;  --查看表结构
 mysql> create database westos;--创建数据库
 Query OK, 1 row affected (0.00 sec)
 exit --推出连接
 -- <注释>

数据库xxx语言

DDL :数据库定义语言

DML:数据库操作语言

DQL:数据库查询语言

DCL:数据库控制语言

操作数据库

  1. 创建数据库

 CREATE DATABASE IF NOT  EXISTS west
  1. 使用数据库

 USE  test
  1. 删除数据库

 DROP DATABASE IF EXISTS westos
  1. 查看数据库

 SHOW DATABASES

数据库的列类型

数值

  • tinyint :十分小 一个字节

  • smallint: 两个字节

  • mediumint:三个字节

  • int :四个字节(常用的)

  • bigint :八个字节

  • float:四个字节(浮点数)

  • double:八个字节(浮点数)

  • decimal:字符串形式的浮点数(金融计算时候)

     

字符串

  • char :固定大小的字节0~255

  • varchar:可变字符串0~65535常用的变量

  • tintext:微型文本 2^8-1

  • text 文本串 2^16-1保存文本

时间日期

  • date :日期YYYY-MM-DD

  • time:时间 HH:mm:ss

  • datetime:YYYY-MM-DD HH:mm:ss

  • timestamp:时间戳,1970.1.1到现在的毫秒数! 也比较常用

  • year:年份表示

null

  • 没有值,未知

  • 注意,不要使用NULL进行运算,结果为NULL

数据库的字段属性(重点)

Unsigned:

  • 无符号的整数

  • 声明了该列,不能声明为负数

zerofill:

  • 0填充的

  • 不足的位数,使用0来填充 int(3),5----005

自增:

  • 通常理解为自增,自动在上一条记录的基础上+1(默认加一,可以修改)

  • 通常用来设计唯一的主键~index,必须是整数类型

  • 可以自定义主键自增的起步初始值和步长

非空:Null not null

  • 假设设置为not null ,如果不给赋值,就会报错

  • null, 如果不填写值,默认就是null!

默认

  • 设置默认的值!

  • sex,默认设置为男,如果不指定该列的值,则会有默认值

拓展

 /*每一个表,都必须存在以下五个字段!未来做项目用的,表示每一个记录存在的意义
 id:主键
 `version`:乐观锁
 is_delete:伪删除
 gmt_create:创建时间
 gmt_update:修改时间
 */

用命令创建数据库中的表

 --命令行创建表
 /*AUTO_INCREMENT:自动递增
 表名和字段名都得加``,防止字段名和表名是关键字
 PRIMARY KEY(`id`):一般只有一个主键
 括号都为英文括号
 DEFAULT :默认字段
 COMMENT:注释
 */
 
 CREATE TABLE IF NOT EXISTS `student`(
 `id` INT(3) NOT NULL AUTO_INCREMENT COMMENT'学号',
 `name` VARCHAR(20) NOT NULL DEFAULT '匿名' COMMENT'姓名',
 `pwd` VARCHAR(20) NOT NULL DEFAULT '123456' COMMENT'密码',
 `age`  INT(3) NOT NULL DEFAULT '18' COMMENT'年龄',
 `sex` VARCHAR(3) NOT NULL DEFAULT '男' COMMENT'性别',
 `birthday`  DATETIME DEFAULT NULL COMMENT'出生日期',
 `email` VARCHAR(20) DEFAULT NULL COMMENT'邮箱',
 PRIMARY KEY(`id`)
  )ENGINE=INNODB   DEFAULT CHARSET=utf8
 --创建表公式
 CREATE TABLE [IF NOT EXISTS] `student`(
    字段名 数据类型 [属性] [索引] [注释],
    字段名 数据类型 [属性] [索引] [注释],
    字段名 数据类型 [属性] [索引] [注释],
    ......
    字段名 数据类型 [属性] [索引] [注释]
 )ENGINE=INNODB   DEFAULT CHARSET=utf8

常用命令

  SHOW CREATE DATABASE school;   -- 查看创建数据库的语句
  --CREATE DATABASE `school` /*!40100 DEFAULT CHARACTER SET utf8 */
  SHOW CREATE TABLE student; -- 查看数据库中的表的语句
 DESC student;  -- 显示表的结构

MYISAM和InnoDB区别

 INNODBMYISAM
事务操作 支持 不支持
数据行锁定 支持 不支持
外键约束 支持 不支持
全文索引 不支持 支持
表空间的大小 较大(约为MYISAM的两倍) 较小

常规使用的操作:

  • MYISAM:节约空间,速度较快

  • INNOODB:安全性高,事务的处理,多表多用户操作

 --关于数据库引擎
 /*
 INNODB :默认使用
 MyISAM :早些年使用
 */

在物理空间存在的位置

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

本质还是文件的存储

  • INNODB在数据库中只有一个

设置数据库的字符集编码

 charset=utf8

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

修改删除表

修改表

 -- 删除表 DROP TABLE [IF EXISTS] 表名;
 DROP TABLE IF EXISTS teacher;
 
 -- 增加表的字段:ALTER TABLE 表名 ADD 添加的字段名 数据类型 [属性]
 ALTER TABLE student1 ADD psw VARCHAR(20) NOT NULL DEFAULT '123456';
 -- 修改表名:ALTER TABLE 表名 RENAME AS 改后的表名;
 ALTER TABLE 表名 RENAME AS 新表名;
 
 ALTER TABLE 表名 MODIFY `字段` 数据类型; -- 修改约束
 
 ALTER TABLE 表名 CHANGE `旧字段名` `新字段名` 数据类型;-- 修改字段名称
 -- 删除表的字段:ALTER TABLE 表名 DROP 字段;
 
 ALTER TABLE student1 DROP pwd;

删除表

 -- 删除表 DROP TABLE 表名;
 DROP TABLE teacher;
  • 所有的创建和删除操作尽量加上判断,以免报错

    注意点:

    • `` 字段名 使用这个包裹

    • 注释/* */

    • sql关键字大小写不敏感,建议写小写

    • 所有符号都写英文

MySQL数据管理

外键(了解即可)

DML语言(全部记住)

数据库意义:存储数据,管理数据

DML:数据操作语言

  • insert

  • update

  • delete

添加

insert

 --添加多条数据语法:INSERT INTO 表名 ([字段名1],[字段名2],[字段名3],) VALUE(),(); 
 INSERT INTO `student1` (`name1`,`age`,`sex`) VALUE('张三','18','男'),('李四','18','女');
 --添加一条数据语法:INSERT INTO 表名 ([字段名1],[字段名2],[字段名3],) VALUE();
 INSERT INTO `student1` (`name1`,`age`,`sex`) VALUE('李四','18','女');
 --不写字段时候,必须与表中的列一一对应
 INSERT INTO `student1`
 VALUE('80','张三','18','男','2020-11-15 06:30:30','122517@qq.com','789654'),('100','李四','18','女','2020-11-15 15:40:59','122517@qq.com','789654');
  • 注意事项:

  1. 符号必须都是英文符号,不能有中文符号;

  2. 字段名必须与value中的值一 一对应;

  3. 字段名可以省略不写,但是value中的值必须与表中列的字段一 一对应;

  4. 多个字段的时候,value用逗号隔开VALUE('张三','18','男'),('李四','18','女');

修改

update 修改谁 (条件) set 字段=赋予新值

 UPDATE `student1` SET `name1`='王麻子'  WHERE id=5;--修改id=5的name字段的值
 UPDATE `student1` SET `name1`='王麻子';--不指定条件的话,把所有的name都改
 UPDATE `student1` SET `name1`='张三',age=68,psw='240162' WHERE id=6;--修改多个字段用逗号隔开即可
 UPDATE `student1` SET `name1`='chenlei',age=68,psw='240162' WHERE id BETWEEN 2 AND 4;-- 改变区间的值

条件:where子句 运算符 id等于某个值,大于某个值,在某个区间内修改....

操作符会返回boolean值

操作符含义范围结果
= 等于 5=6 false
!=或者<> 不等于 5<>6 true
> 大于    
< 小于    
>= 大于等于    
<= 小于等于    
between...and 在某个范围内 [2,5]  
and 我和你&& 5>1and1>5 false
or 我或你|| 5>1and1>5 true

语法:update 表名 set colnum_name=value,[colnum_name=value].... where条件

注意:

  • colum_name是数据库的列,尽量带上``

  • 条件,筛选的条件,如果没有指定,则会修改所有的列

  • value,是一个具体的值,也可以是一个变量

  • 多个设置的属性之间,使用英文逗号隔开

删除

delete命令

语法:delete from 表明 [where 条件]

 DELETE  FROM student1;-- 删除表中所有数据
 DELETE FROM student1 WHERE id=101;-- 添加条件得删除

TRUNCATE命令

作用:完全清空一个数据库表,表的结构和索引约束不会变

 TRUNCATE student1;-- 删除表中所有数据

delete 和truncate的区别

相同点:都能删除数据,都不会删除表结构

不同点:

  • turncate 重新设置自增列 计数器会归零

  • truncate 不会影响事务

 DELETE  FROM student1; --不会影响自增
 TRUNCATE student1; --自增会归零

了解:delete删除问题,重启数据库,现象

  • Innodb: 自增列会重1开始(存在内存当中,关机即失)

  • MyISAM:继续上一个自增量开始(存在文件中,不会丢失)

DQL查询数据(最重点)

(Database Query Language:数据库查询语言)

  • 所有的查询操作都用它,Select

  • 简单的查询。复杂的查询都用它

  • 数据库最核心的语言,最重要的语言

  • 使用频率最高的语言

select语法

 SELECT [ALLI DISTINCT]
 {* 1 table.* | [table.field1[as alias1][,table. field2[as alias2]][....]]}
 FROM table_ name [as table_ _alias]
 [left | right 1 inner join table_ name2] -- 联合查询
 [WHERE ...] -- 指定结果需满足的条件
 [GROUP BY ...1] -- 指定结果按照哪几个字段来分组
 [HAVING] -- 过滤分组的记录必须满足的次要条件
 [ORDER BY ...] --指定查询记录按一个或多个条件排序
 [LIMIT {[offset,]row_ count | row_ countOFFSET offset}];
 --指定查询的记录从哪条至哪条

 

SELECT * FROM student1;-- 查询表中所有的数据

SELECT `name1`,`age` FROM student1;-- 查询表中特有的字段

-- 把字段改为自己想要的字段,表和字段都可以改,用as连接
SELECT  `name1` AS 姓名, `sex` AS 性别 ,`age` AS 年龄 FROM student1 AS s;
-- 函数CONCAT('年龄:',`age`)
SELECT CONCAT('年龄:',`age`) AS 新年龄 FROM student1;

 

去重distant

作用:去除select查询出来的结果中重复的数据

SELECT DISTINCT age FROM student1; -- 去掉字段中重复的数据,只显示一条

 

数据库的列(表达式)

SELECT VERSION(); --查询系统版本
SELECT 100*2-1 AS 计算结果:;
SELECT `name1`,`age`+2 AS 新年龄  FROM student1;-- 全体年龄加一

数据库中的表达式: 文本值,列,NUll,函数,计算表达式,系统变量

select 表达式 from 表

where条件子句

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

搜索的条件由一个或多个表达式组成!结果为布尔值

逻辑运算符

运算符语法描述
and && a and b a&&b 逻辑与,两个都为真,结果为真
or a or b a||b 逻辑或,其中一个为真,则结果为真
not not a !a 逻辑非,真为假,假为真!

尽量使用英文字母

-- 查询年龄和姓名,并且年龄在20-50之间,
SELECT `name1`,`age` FROM student1 WHERE age BETWEEN 20 AND 50;
-- 查询年龄和姓名,并且年龄在20-50之间,
SELECT `name1`,`age` FROM student1 WHERE age BETWEEN 20 AND 50;
-- 查询年龄大于20,并且小于50的名字
SELECT `name1`,`age` FROM student1 WHERE age>=20 AND age<=50;
-- 查询年龄不等于18岁的名字
SELECT `name1` AS 姓名,`age` AS 年龄 FROM student1 AS 学生表 WHERE NOT  age=18;

模糊查询

模糊查询(比较运算符)

运算符语法描述
is null a is null 如果操作符为null,结果为真
is not null a is not null 如果操作符不为null,结果为真
between a bewteen b an c 若a在b和c之间 结果为真
like a like b sql匹配,如果a匹配b,则结果为真
in a in (a1,a2,a3......) 假设a在a1,或者a2....其中摸一个值中,结果为真
-- ============= like模糊查询(like只能在like中使用)  =============
-- 查询姓陈的
SELECT `name1`,`age` FROM student1 WHERE `name1` LIKE '陈%';
-- 查询姓陈的,知道具体名字为几个字
SELECT `name1`,`age` FROM student1 WHERE `name1` LIKE '陈_';
-- 查询姓名中带有'佳'字
SELECT `name1`  FROM student1 WHERE `name1` LIKE '%佳%';

-- ==============in(是一个准确的值,不能用%) ===================
SELECT `name1`,`age` FROM student1 WHERE `age` IN (18,66);

-- ==============is null   not is null===========================
-- 查询 email 为空的学生名字
SELECT `name1`,`email` FROM  student1 WHERE `email` IS NULL;

SELECT `name1`,`email` FROM  student1 WHERE `email` IS NULL OR `email`=''; -- 空

SELECT `name1`,`email` FROM  student1 WHERE `email`=''; -- 空字符串

-- 查询 email 不为空的学生名字
SELECT `name1`,`email`  FROM student1 WHERE `email` IS NOT NULL;

-- ===================between ========================
-- 查询年龄在18-30之间的名字
SELECT `name1`,`age` FROM student1 WHERE age BETWEEN 18 AND 30;

联表查询join

image-20200430134544722

操作描述
inner join 如果表中至少有一个匹配,就返回行
left join 会从左表中返回所有的值,即使右表中没有匹配
right join 会从右表中返回所有的值,即使左表中没有匹配
`test`-- ====================联表查询========================
/*思路:
1.分析需求,分析查询的字段来自哪些表(连接查询)
2.确定使用哪种连接查询?七种,
确定交叉点(这两个表中哪个数据是相同的)
判断条件:学生表中的id=成绩表 id
*/
-- 查询参加了考试的同学(学号id,姓名,科目编号,分数)
-- join (连接的表) on (判断条件) 连接查询
-- where 等值查询
-- =================inner================
SELECT s.`StudentNo`,`StudentName`,`SubjectNo`,`StudentResult` 
FROM  student AS s
INNER JOIN result AS r
ON s.`StudentNo`=r.`StudentNo`;



-- ==================left===============
SELECT s.`StudentNo`,`StudentName`,`SubjectNo`,`StudentResult` 
FROM  student AS s
LEFT JOIN result AS r
ON s.`StudentNo`=r.`StudentNo`;


-- ==================right===============
SELECT s.`StudentNo`,`StudentName`,`SubjectNo`,`StudentResult` 
FROM  student AS s
RIGHT JOIN result AS r
ON s.`StudentNo`=r.`StudentNo`;`result``student``result``student`
-- ===========查询缺考学生=================
SELECT s.`StudentNo`,`StudentName`,`SubjectNo`,`StudentResult` 
FROM  student AS s
RIGHT JOIN result AS r
ON s.`StudentNo`=r.`StudentNo`
WHERE  StudentResult IS NULL

自连接以及联表查询

自连接:自己的表和自己的表连接,核心:一张表拆为两张一样的表即可

分析:

父类:

categoryidcategoryName
2 信息技术
3 软件开发
5 美术设计

子类:

pidcategoryidcategoryName
2 8 办公信息
5 7 ps技术
3 6 web开发
3 4 数据库

父类对应子类的关系

  
信息技术 办公信息
软件开发 数据库
美术设计 ps技术
软件开发 web开发

 

CREATE TABLE `category` (
`categoryid` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主题id',
`pid` INT(10) NOT NULL COMMENT '父id',
`categoryName` VARCHAR(50) NOT NULL COMMENT '主题名字',
PRIMARY KEY (`categoryid`)
) ENGINE=INNODB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8

-- 插入数据
INSERT INTO `category` (`categoryid`, `pid`, `categoryName`)
VALUES('2','1','信息技术'),
('3','1','软件开发'),
('4','3','数据库'),
('5','1','美术设计'),
('6','3','web开发'),
('7','5','ps技术'),
('8','2','办公信息');


-- =============自连接=====================

SELECT c.categoryName AS '父类', b.categoryName AS '子类'
FROM category  AS c , category AS b
WHERE c.categoryid=b.pid

分页和排序

分页limit

-- ================分页=======================
SELECT s.`StudentNo`,`StudentName`,`StudentResult` 
FROM  student  AS s
INNER JOIN result AS r
WHERE `StudentResult` IS NOT NULL
ORDER BY `StudentResult` DESC 
LIMIT 0,5;
-- ============================================
/*分页语法:
第一页: LIMIT 0,5;  (1-1)*5
第二页: LIMIT 5,10;  (2-1)*5
第三页: LIMIT 10,15;   (3-1)*5
第n页:  LIMIT ?,?;   (n-1)*pageSize

【pageSize:页面大小】
【(n-1)*pageSize:起始值】
【n:当前页】
【数据总数/页面大小=总页数】 数据总数/页面大小 除下不等于0页面数加一
*/

 

排序order by 升序asc 降序 desc

-- =============升序=============================
SELECT s.`StudentNo`,`StudentName`,`StudentResult` 
FROM  student  AS s
INNER JOIN result AS r
WHERE `StudentResult` IS NOT NULL
ORDER BY `StudentResult` ASC ;
-- ==============降序========================
SELECT s.`StudentNo`,`StudentName`,`StudentResult` 
FROM  student  AS s
INNER JOIN result AS r
WHERE `StudentResult` IS NOT NULL
ORDER BY `StudentResult` DESC ;

语法:limit(查询起始的下标,pageSize)

子查询和嵌套查询

 

常用的函数

时间和日期函数

-- ==========常用的函数===============
SELECT VERSION();-- 获取版本
SELECT SYSDATE(NOW()); --
SELECT NOW(); -- 获取当前时间日期
SELECT CURRENT_DATE(); -- 获取当前日期
SELECT USER(); -- 当前用户
SELECT SYSDATE(); -- 获取系统时间
SELECT LOCALTIME(); -- 获取本地时间

聚合函数

函数名称描述
count() 计数
sum() 求和
avg() 求平均数
max() 最大值
min() 最小值
-- ================聚合函数==============
-- 三种都能进行计数,COUNT(`StudentName`)计算具体列的数
-- 不会把NUll进行计数,
SELECT COUNT(`StudentName`) FROM student;
SELECT COUNT(`LoginPwd`) FROM student;
-- 不会忽略null值,  本质  计算行数
SELECT COUNT(*) FROM student; 
-- 不会忽略所有的NULL值, 本质 计算行数 
SELECT COUNT(1) FROM student; 

SELECT SUM(`StudentResult`) AS '总和' FROM result;
SELECT AVG(`StudentResult`) AS '平均数' FROM result;
SELECT MAX(`StudentResult`) AS '最大值' FROM result;
SELECT MIN(`StudentResult`) AS '最小值' FROM result;

分组和过滤

SELECT SubjectName, AVG (StudentResult) AS平均分, MAX (StudentResult) ,MIN (StudentResult)
FROM result r
INNER JOIN subject sub
ON r.SubjectNoi = sub.SubjectNo
GROUP BY r.SubjectNo --通过什么字段来分组
HAVING 平均分>80

数据库加密级别的MD5加密

MD5不可逆,具体的值得MD5是一样的

MD5破解网站的原理,背后有一个字典,MD5加密后的值,加密前的值

 

-- ===========MD5加密===========================

-- 插入数据时加密
 INSERT INTO `student` (`StudentNo`,`LoginPwd`,`StudentName`) VALUE('1005',MD5('123456'),'陈磊');

-- 把明文密码加为密文密码
UPDATE `student` SET LoginPwd=MD5(LoginPwd) WHERE StudentNo=1000;

-- 把全部明文密码改为密文 
UPDATE `student` SET LoginPwd=MD5(LoginPwd);

Select 总结

image-20200430222041273

事务

什么是事务?

要么都成功,要么都失败


一一一一一一一一

1.SQL执行 A给B转账

2.SQL执行 B收到A的钱

一一一一一一一一

将一组SQL放在一个批次中去执行~

事务原则 ACID原则 :原子性,一致性,隔离性,持久性 ()脏读,幻读.....

原子性(A):

要么都成功,要么都失败

一致性(C):

事务前后的数据完整性要保持一致,1000

隔离性(I):

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

持久性(D):

事务一旦提交则不可逆,被持久到数据库中

隔离所导致的一些问题

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

不可重复度:在一个事务内读取表中的某一 行数据,多次读取结果不同。 (这个不一-定是错误,只是某些场合不对)

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

执行事务

  • MySQL是默认开启事务自动提交的

-- MYSQL 是默认开启事务自动提交的
SET autocommit = 0 -- 关闭
SET autocommit = 1 -- 开启,默认开启

-- 手动处理事务
SET autocommit = 0 -- 关闭自动提交

-- 事务开启
START TRANSACTION -- 标记一个事务的开始,从这个之后的 sql 都在同一个事务内

INSERT xx
INSERT xx

-- 提交:持久化(成功)
COMMIT
-- 回滚:回到原来的样子(失败)
ROLLBACK

-- 事务结束

SET autocommit = 1 -- 开启自动提交

-- 了解

SAVEPOINT 保存点   -- 设置一个事务的保存点
ROLLBACK TO SAVEPOINT  保存点 -- 回滚到保存点

RELEASE SAVEPOINT  保存点 -- 撤销保存点

模拟场景

CREATE DATABASE IF NOT EXISTS shop CHARSET utf8 COLLATE utf8_general_ci;  -- 创建数据库

CREATE TABLE IF NOT EXISTS `account`(
`id`  INT(3) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(20) NOT NULL ,
`money` DECIMAL(9,2) NOT NULL,
PRIMARY KEY (`id`)

)ENGINE = INNODB  DEFAULT CHARSET = utf8  -- 创建表

-- 添加数据
INSERT INTO `account` (`name`,`money`) VALUES('A',2000.00),('B',10000.00);
 
SELECT * FROM account;

SET autocommit = 0; -- 关闭事务自动提交
START TRANSACTION;  -- 开启事务
-- 一组事务
UPDATE `account` SET money=money-500  WHERE `name`='A';
UPDATE `account` SET money=money+500  WHERE `name`='B';

COMMIT ;  -- 提交事务(事务一旦被提交,就被持久化了,不能回滚了)
ROLLBACK  -- 回滚

SET autocommit = 1;  -- 恢复自动提交

image-20200503183553504

索引

索引(Index)是帮助MYSQL高效获取数据的数据结构

  • 主键索引 (PRIMARY KEY)

    • 唯一的标识,主键不可重复,只能有一个列作为主键

  • 唯一索引(UNIQUE KEY)

    • 避免重复的列出现,唯一索引可以重复,多个列都可以标识唯一索引

  • 常规索引(KEY/Index)

    • 默认的,index,key关键字来设置

  • 全文索引(FullText)

    • 在特定数据库引擎下才有,Myisam

    • 快速定位数据

基础语法:

-- ==================索引==========================
-- 1.在创建表的时候给字段添加索引
-- 2.创建表完毕后,增加索引
-- 显示所有的索引信息

SHOW  INDEX  FROM  `student`;

-- 增加一个(索引名) 列名

ALTER  TABLE `student` ADD  INDEX s_name (`s_name`);

-- 创建索引
-- id_表明_字段名
-- create index 索引名 on 表(字段)
CREATE INDEX id_student_s_birth ON s_birth(`s_birth`);

-- EXPLAIN 分析sql执行的状况

EXPLAIN SELECT * FROM student; -- 非全文索引

EXPLAIN SELECT * FROM WHERE MATCH(`s_name`) AGAINST('刘');

索引原则

  • 索引不是越多越好

  • 不要对进程变动数据加索引

  • 小数据量的表不需要加索引

  • 索引一般加在常用来查询的字段上

索引的数据结构

Hash类型的索引

Btree:InnoDB的默认数据结构

权限管理

可视化:

image-20200503224347802

 

命令操作语法:

-- ===================权限=============================
-- 创建用户   CREATE USER 用户名 IDENTIFIED BY '密码';  identified
CREATE USER chenlei1 IDENTIFIED BY '123456';  
-- 修改密码(--当前用户)
SET PASSWORD = PASSWORD('123456');
-- 修改密码(--指定用户)
SET PASSWORD FOR chenlei1=PASSWORD('111111');
-- 重命名  RENAME USER 原用户名 TO 新用户名;
RENAME USER chenlei1 TO chenchen;
-- 用户授权 ALL PRIVILEGES 全部权限,*.*意思为(库.表)
-- ALL PRIVILEGES 除了不能有root的grant(授予其他用户权限)权限,其他都能
GRANT ALL PRIVILEGES ON *.* TO chenchen;
-- 查看权限
SHOW GRANTS FOR chenchen; -- 查看指定用户权限  Grants for chenchen@% GRANT ALL PRIVILEGES ON *.* TO 'chenchen'@'%' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9'
SHOW GRANTS FOR root@localhost;  -- 查看root用户  GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' WITH GRANT OPTION


-- 撤销权限
REVOKE ALL PRIVILEGES ON *.* FROM chenchen;

-- 删除用户
DROP  USER chenchen;

MySQL备份

作用:

  • 保证数据不丢失

  • 数据转移

MySQL数据库备份方式

  • 直接拷贝物理文件

  • 在Sqlyog这种可视化工具手动导出

    image-20200504141028942

  • 使用命令行到处mysqldump 命令行使用

-- 单张表 导出
C:\Users\16225>mysqldump -hlocalhost -uroot -p123456 school student> d:1.sql
-- 多张表  导出
C:\Users\16225>mysqldump -hlocalhost -uroot -p123456 school student result> d:2.sql
-- 整个数据库  导出
C:\Users\16225>mysqldump -hlocalhost -uroot -p123456 school > d:3.sql
-- 数据库导入
C:\Users\16225>mysql -uroot -p123456
mysql> use school;
Database changed
mysql> source d:3.sql

设置数据库的步骤

  • 收集信息,分析需求

    • 用户表(用户登录注销,用户的个人信息,写博客,创建分类)

    • 分类表(文章分类,谁创建的)

    • 文章表(文章的信息)

    • 评论表

    • 友链表(友链信息)

    • 自定义表(系统信息,某个关键的字,或者一些主字段) key : value

    • 说说表(发表心情.. id... conte...create. _time)

  • 标识实体(把需求落地到每个字段)

  • 标识实体之间的关系

    • 写博客: user --> blog

    • 创建分类: user -> category

    • 关注: user ->user

    • 友链: links

    • 评论: user-user-bl

数据库三大范式

三大范式

第一范式(1NF)

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

第二范式(2NF)

前提:满足第一范式

没一张表只描述一件事情

第三范式(3NF)

前提:满足第一范式和第二范式

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

(规范数据库设计)

规范性 和 性能的问题

关联查询的表不得超过三张表

  • 考虑商业化的需求和目标,(成本、用户体验)数据库性能更加重要

  • 在规范性能问题的时候,需要适当的考虑一下 规范性

  • 故意给某些表增加一些冗余的字段(从多表查询变为单表查询)

  • 故意增加一些计算列(从大数据量降低为小数据量的查询:索引)

JDBC(重点)

数据库驱动

新建lib目录,把数据库jar包粘贴到lib目录下,右键add as library 添加到库

image-20200504154732718

-- 创建数据库
CREATE DATABASE jdbcstudy CHARACTER SET utf8 COLLATE utf8_general_ci;
USE jdbcstudy;
CREATE TABLE users(
`id` INT PRIMARY KEY,
`name` VARCHAR (40),
`password` VARCHAR(40),
 email VARCHAR(60),
 birthday DATE
);
INSERT INTO users(id, `name`, `password`,email, birthday)
VALUES(1, 'zhansan', '123456', 'zs@sina.com', '1980-12-04'),
(2,'lisi', '123456', '1isi@sina.com', '1981-12-04'),
(3,'wangwu' , '123456' ,'wangwu@sina.com','1979-12-04');

-- =================================
import javax.print.attribute.standard.MediaSize;
import java.sql.*;

public class JDBCFirstDemo {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        // 创建驱动
        Class.forName("com.mysql.jdbc.Driver");
        // 用户信息和url
        String url="jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
        String user="root";
        String pwd="123456";
        //连接成功,数据库对象,
        Connection connection = DriverManager.getConnection(url, user, pwd);
       //执行sql的对象  Statement 为执行的对象
        Statement statement = connection.createStatement();
        String sql="select * from users";
        ResultSet resultSet = statement.executeQuery(sql);
        while (resultSet.next()){
            System.out.println("id="+resultSet.getObject("id"));
            System.out.println("name="+resultSet.getObject("name"));
            System.out.println("pwd="+resultSet.getObject("password"));
            System.out.println("email="+resultSet.getObject("email"));
            System.out.println("birth="+resultSet.getObject("birthday"));

        }
        if (resultSet!=null){
            resultSet.close();
        }
        if (statement!=null){
            statement.close();
        }
        if (connection!=null){
            connection.close();
        }
    }
}

JDBC步骤:

  1. 加载驱动

  2. 连接数据库DriveManager

  3. 获得执行sql对象的statement

  4. 获得返回的结果集(查询才有的)

  5. 释放连接

DriverManager

 Class.forName("com.mysql.jdbc.Driver"); //固定写法
  Connection connection = DriverManager.getConnection(url, user, pwd);
/*
connection代表数据库
数据库设置自动提交
事务提交
事务回滚
*/
connection.rollback();
connection.commit();
connection.getAutoCommit();

URL

 String url="jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
//Mysql--3306
//协议://地址:端口号/数据库名
//oralce--1521
//jdbc:oralce:thin:@localhost:1521:sid

Statement 执行SQL对象 PrepareStatement执行SQL对象

  statement.executeQuery(); //查询 返回 ResultSet
        statement.executeUpdate();  //插入、更新、删除  返回受影响的行数
        statement.execute(); //任何sql语句

ResultSet 查询指定的结果集:封装了所有查询结果

获得指定的数据类型

  resultSet.getObject(); //任何类型都可以用这个
        resultSet.getInt();  //获取整型
        resultSet.getFloat();//获取单精度浮点数
        resultSet.getDouble();//获得双精度浮点数
        resultSet.getString(); //获得字符串类型

遍历

resultSet.next();  //移动到后一个
resultSet.previous(); //移动到前一个
resultSet.beforeFirst();  //移动到最前面
resultSet.afterLast();   //移动到最后面

释放连接

 if (resultSet!=null){
            resultSet.close();
        }
        if (statement!=null){
            statement.close();
        }
        if (connection!=null){
            connection.close();
        }
//关闭资源有后向前关闭

Statement对象

代码实现

驱动实现

package com.chenlei.lesson02.utils;

import jdk.nashorn.internal.ir.IfNode;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class JdbcUtils {
        private static String driver=null;
        private static String url=null;
        private static String username=null;
        private static String password=null;
    static {
        try {
            InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
            Properties properties = new Properties();
            properties.load(in);
             driver = properties.getProperty("driver");
             url = properties.getProperty("url");
             username = properties.getProperty("username");
             password = properties.getProperty("password");
             Class.forName(driver);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    //获取连接
    public static Connection getConnection() throws SQLException {
       return DriverManager.getConnection(url, username, password);
    }
    //释放资源
    public static  void release(Connection con, Statement st, ResultSet re){
        try {
            if (re!=null){
                re.close();
            }
            if (st!=null){
                st.close();
            }
            if (con!=null){
                con.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }
}

package com.chenlei.lesson02;

import com.chenlei.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestInsert {
    public static void main(String[] args) {
        Connection conn = null;
        Statement st = null;
        ResultSet re = null;
        try {
            conn = JdbcUtils.getConnection();
            st = conn.createStatement();
            String sql="INSERT INTO users(id, `name`, `password`,email, birthday)\n" +
                    "VALUES(5, 'chenlei', '123456', 'superstudyc@163.com', '2020-12-04')";
            int i = st.executeUpdate(sql);
            if(i>0){
                System.out.println("插入成功");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,re);
        }
    }
}

package com.chenlei.lesson02;

import com.chenlei.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestDelete {
    public static void main(String[] args) {
        Connection conn = null;
        Statement st = null;
        ResultSet re = null;
        try {
            conn = JdbcUtils.getConnection();
            st = conn.createStatement();
            String sql="DELETE  FROM `users` WHERE id=3;";
            int i = st.executeUpdate(sql);
            if(i>0){
                System.out.println("删除成功");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,re);
        }
    }
}

package com.chenlei.lesson02;

import com.chenlei.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestUpdate {
    public static void main(String[] args) {
        Connection conn = null;
        Statement st = null;
        ResultSet re = null;
        try {
            conn = JdbcUtils.getConnection();
            st = conn.createStatement();
            String sql="UPDATE `users` SET `name`='chenlong',`password`='11111',`email`='2401620421@qq.com',`birthday`='2020-12-04' WHERE id=2;";
            int i = st.executeUpdate(sql);
            if(i>0){
                System.out.println("更新成功");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,re);
        }
    }
}

package com.chenlei.lesson02;

import com.chenlei.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestSelect {
    public static void main(String[] args) {
        Connection conn=null;
        Statement st=null;
        ResultSet re=null;
        try {
             conn=JdbcUtils.getConnection();
             st=conn.createStatement();

            String sql="SELECT  `name` FROM users WHERE id=4;";
            re=st.executeQuery(sql);
            while (re.next()){
                System.out.println(re.getString("name"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(conn,st,re);
        }
    }
}

配置文件

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true
username=root
password=123456

SQL注入问题

数据库漏洞

package com.chenlei.lesson02;

import com.chenlei.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class Sql注入 {
    public static void login(String username,String password){
        Connection conn=null;
        Statement st=null;
        ResultSet re=null;
        try {
            conn= JdbcUtils.getConnection();
            st=conn.createStatement();

            String sql="select * from users";
            re=st.executeQuery(sql);
            while (re.next()){
                System.out.println(re.getString("name"));
                System.out.println(re.getString("password"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(conn,st,re);
        }
    }

    public static void main(String[] args) {
            login("''or 1=1 "," '' or 1=1");
    }

}

PreparedStatement对象

作用:防止SQL注入,效率更高

package com.chenlei.lesson03;

import com.chenlei.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestIsert {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet re = null;
        try {
            conn = JdbcUtils.getConnection();
            String sql = "insert into users (id, name, password, email, birthday) VALUES (?,?,?,?,?)";
            st = conn.prepareStatement(sql);
            st.setInt(1,8);
            st.setString(2,"赵六");
            st.setString(3,"12789");
            st.setString(4,"789@qq.com");
            st.setString(5,"2023-04-04");
            int i = st.executeUpdate();
            if (i>0){
                System.out.println("插入数据成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(conn,st,re);
        }
    }
}

package com.chenlei.lesson03;

import com.chenlei.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestDelete {
    public static void main(String[] args) {
        Connection con=null;
        PreparedStatement st=null;
        ResultSet re=null;
        try {
            con = JdbcUtils.getConnection();
            //值用?标识
            String sql="delete  from users where id=?";
            st= con.prepareStatement(sql);  //预编译  先写sql 不执行
            //给预编译的?赋值
            st.setInt(1,8);
            int i = st.executeUpdate();
            if (i>0){
                System.out.println("删除成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(con,st,re);
        }
    }
}

package com.chenlei.lesson03;

import com.chenlei.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestUpdate {
    public static void main(String[] args) {
        Connection con=null;
        PreparedStatement st=null;
        ResultSet re=null;
        try {
            con = JdbcUtils.getConnection();
            //值用?标识
            String sql="update users set `name`=?, password=?, email=? ,birthday=? where id=?";
            st= con.prepareStatement(sql);  //预编译  先写sql 不执行
            //给预编译的?赋值   parameterindex是按照?来的,第一个?第一列以此类推
            st.setString(1,"高兴");
            st.setString(2,"789456");
            st.setString(3,"1622517097@163.com");
            st.setString(4,"2020-10-20");
            st.setInt(5,1);
            int i = st.executeUpdate();
            if (i>0){
                System.out.println("修改成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(con,st,re);
        }
    }
}

package com.chenlei.lesson03;

import com.chenlei.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestSelect {
    public static void main(String[] args) {
        Connection con=null;
        PreparedStatement st=null;
        ResultSet re=null;
        try {
            con=JdbcUtils.getConnection();
            String sql="select `name`,password from users where id=?;";
            st= con.prepareStatement(sql);
            st.setInt(1,1);
            re = st.executeQuery();
            while (re.next()){
                System.out.println("用户名为:"+re.getString("name"));
                System.out.println("密码为:"+re.getString("password"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(con,st,re);
        }
    }
}

用IDEA连接数据库

连接数据库

image-20200504211906177

image-20200504211936504

选择你想要显示的数据库 image-20200504212709355

image-20200504212911334

命令行输入sql语句 image-20200504213522470

自动提交事务

ACID原则

原子性:要么成功,要么失败

一致性:提交前后数据总数不变

隔离性:多个进程互不干扰

持久性:事务一旦提交不可恢复,被持久化到数据库当中

隔离性产生的问题:

脏读:一个事务读取了另一个没有提交的事务

不可复读:在一个事务内重复读取数据,表数据发生了改变

虚度(幻读):在一个事务内,读取到了别人插入的数据,导致前后读取出来的数据不一致

package com.chenlei.lesson04;

import com.chenlei.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestWork {
    public static void main(String[] args) {
        Connection con=null;
        PreparedStatement st=null;
        ResultSet re=null;
        try {
            con=JdbcUtils.getConnection();
            con.setAutoCommit(false);  //关闭自动提交,默认事务自动开启   和sql里面不一样
            String sql1="update account set money=money-100 where id=1";
            st=con.prepareStatement(sql1);
            st.executeUpdate();

            String sql2="update account set money=money+100 where id=2";
            st=con.prepareStatement(sql2);
            st.executeUpdate();
            con.commit(); //提交事务
            System.out.println("成功");
        } catch (SQLException e) {
            try {
                con.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
    }
}

数据库连接池

最小连接数:

最大连接数:

等待超时:

编写连接池:实现一个DataSource接口

开源数据源实现

DBCP

C3P0

Druid:阿里巴巴

使用了这些数据库连接池之后,我们在项目中就不需要编写连接数据库的代码了

 

DBCP

需要得jar包:commons-pool-1.6jar commons-dbcp-1.4jar

image-20200505213532396

配置文件:

#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true
username=root
password=123456

#
initialSize=10

#最大连接数量
maxActive=50

#
maxIdle=20

#
minIdle=5

#
maxWait=60000

#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]
#注意:“user” 与 “password” 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=gbk

#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true

#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED

 

package com.chenlei.lesson05.utils;

import org.apache.commons.dbcp.BasicDataSourceFactory;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class JdbcUtils_DBCP {
    private static DataSource dataSource = null;

    static {
        try {
            InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("db.properties");
            Properties properties = new Properties();
            properties.load(in);
            //创建数据源
            dataSource = BasicDataSourceFactory.createDataSource(properties);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //获取连接
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();  //从数据源中获取连接
    }

    //释放资源
    public static void release(Connection con, Statement st, ResultSet re) {
        try {
            if (re != null) {
                re.close();
            }
            if (st != null) {
                st.close();
            }
            if (con != null) {
                con.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }
}

 

C3P0

image-20200505213504777

<c3p0-config>
    <!-- 使用默认的配置读取连接池对象 -->
    <default-config>
        <!-- 连接参数 -->
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/bd3</property>
        <property name="user">root</property>
        <property name="password">root</property>
 
        <!-- 连接池参数 -->
        <!-- 初始化申请的连接数量 -->
        <property name="initialPoolSize">5</property>
        <!-- 最大的连接数量 -->
        <property name="maxPoolSize">10</property>
        <!-- 超时时间 3秒 -->
        <property name="checkoutTimeout">3000</property>
    </default-config>
 
    <named-config name="Mysql">
        <!-- 连接参数 -->
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=true</property>
        <property name="user">root</property>
        <property name="password">123456</property>
 
        <!-- 连接池参数 -->
        <property name="initialPoolSize">5</property>
        <property name="maxPoolSize">8</property>
        <property name="checkoutTimeout">1000</property>
    </named-config>
</c3p0-config>

代码:

package com.chenlei.lesson05.utils;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JdbcUtils_C3P0 {
    private static DataSource dataSource = null;

    static {
        try {
           //配置文件写法
            dataSource = new ComboPooledDataSource("Mysql");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //获取连接
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();  //从数据源中获取连接
    }

    //释放资源
    public static void release(Connection con, Statement st, ResultSet re) {
        try {
            if (re != null) {
                re.close();
            }
            if (st != null) {
                st.close();
            }
            if (con != null) {
                con.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }
}
posted @ 2020-05-06 20:28  Crazylearningjava  阅读(214)  评论(0)    收藏  举报