1 初识MySQL
1.1 MySQL连接
命令行连接!
mysql -uroot -p --连接数据库
flush privileges; --刷新权限
-----------------------------------------------------------
-- 所有的语句都使用;结尾
show databases; --查看所有的数据库
mysql> use mysql --切换数据库 use
Database changed
show tables; --查看数据库中所有的表
describe db; --查看数据库表结构
create database westos; --创建一个数据库
exit; --退出连接
-- 单行注释(SQL的本来注释)
/* (SQL的多行注释)
111
222
*/
1.2 数据库的语言
数据库 xxx 语言 CRUD 增删改查!
DDL 定义
DML 操作
DQL 查询
DCL 控制
2 操作数据库
操作数据库>操作数据库中的表>操作数据库中表的数据
MySQL关键字不区分大小写
2.1 操作数据库
1、创建数据库
create database [if not exists] 库名;
2、删除数据库
drop database [if exists] 库名;
3、使用数据库
--tab键的上面,如果你的表名或者字段名是一个特殊字符,就需要带 ` `
use `库名`
4、查看数据库
show databases; --查看所有数据库
2.2 数据库的列类型
数值
字符串
时间日期
2.3 数据库的字段属性(重点)
2.4 创建数据库表(重点)
2.5 数据表的类型
2.6 修改删除表
3 MySQL数据管理
3.1 外键(了解即可)
删除有外键关系的表的时候,必须要先删除引用别人的表(从表),再删除被引用的表(主表)
3.2 DML语言(全部记住)
添加、修改、删除
3.3 添加
3.4 修改
3.5 删除
4 DQL查询数据(最重点)
4.1 DQL
4.2 指定查询字段
有时候,列名字不是那么的见名知意。我起别名 AS 字段名 as 别名 表名 as 别名
4.3 where条件子句
作用:检索数据中符合条件的值
搜索的条件由一个或者多个表达式组成!结果 布尔值
4.4 联表查询(重难点)
Jion对比
测试
/*
**连接查询
如需要多张数据表的数据进行查询,则可通过连接运算符实现多个查询
内连接 inner join
查询两个表中的结果集中的交集
外连接 outer join
左外连接 left join
(以左表作为基准,右边表来一一匹配,匹配不上的,返回左表的记录,右表以NULL填充)
右外连接 right join
(以右表作为基准,左边表来一一匹配,匹配不上的,返回右表的记录,左表以NULL填充)
等值连接和非等值连接
自连接**
*/
-- 查询参加了考试的同学信息(学号,学生姓名,科目编号,分数)
SELECT * FROM student;
SELECT * FROM result;
/*思路:
(1):分析需求,确定查询的列来源于两个类,student result,连接查询
(2):确定使用哪种连接查询?(内连接)
*/
SELECT s.studentno,studentname,subjectno,StudentResult
FROM student s
INNER JOIN result r
ON r.studentno = s.studentno
-- 右连接(也可实现)
SELECT s.studentno,studentname,subjectno,StudentResult
FROM student s
RIGHT JOIN result r
ON r.studentno = s.studentno
-- 等值连接
SELECT s.studentno,studentname,subjectno,StudentResult
FROM student s , result r
WHERE r.studentno = s.studentno
-- 左连接 (查询了所有同学,不考试的也会查出来)
SELECT s.studentno,studentname,subjectno,StudentResult
FROM student s
LEFT JOIN result r
ON r.studentno = s.studentno
-- 查一下缺考的同学(左连接应用场景)
SELECT s.studentno,studentname,subjectno,StudentResult
FROM student s
LEFT JOIN result r
ON r.studentno = s.studentno
WHERE StudentResult IS NULL
-- 思考题:查询参加了考试的同学信息(学号,学生姓名,科目名,分数)
SELECT s.studentno,studentname,subjectname,StudentResult
FROM student s
INNER JOIN result r
ON r.studentno = s.studentno
INNER JOIN `subject` sub
ON sub.subjectno = r.subjectno
-- 编写SQL语句,将栏目的父子关系呈现出来 (父栏目名称,子栏目名称)
-- 核心思想:把一张表看成两张一模一样的表,然后将这两张表连接查询(自连接)
SELECT a.categoryName as '父栏目',b.categoryName as '子栏目'
from category as a,category as b
WHERE a.categoryid = b.pid
Practise
-- 查询学员及所属的年级(学号,学生姓名,年级名)
select studentno as '学号',studentname as '学生姓名',gradename as '年级名'
FROM student as stu INNER JOIN grade as g
on stu.gradeid=g.gradeid
-- 查询科目及所属的年级(科目名称,年级名称)
SELECT subjectname as 科目名称,gradename as 年级名称
FROM `subject` as sub INNER JOIN grade as g
on sub.gradeid=g.gradeid
-- 查询 高等数学-3 的所有考试结果(学号 学生姓名 科目名称 成绩)
SELECT stu.studentno as 学号,studentname as 学生姓名,subjectname as 科目名称,studentresult as 成绩
from student as stu INNER JOIN result as r
on stu.studentno=r.studentno
INNER JOIN `subject` sub
on r.subjectno=sub.subjectno
where subjectname='高等数学-3'
4.5 排序和分页
排序
语法 : ORDER BY
ORDER BY 语句用于根据指定的列对结果集进行排序。
ORDER BY 语句默认按照ASC升序对记录进行排序。
如果您希望按照降序对记录进行排序,可以使用 DESC 关键字。
-- 查询 高等数学-3 的所有考试结果(学号 学生姓名 科目名称 成绩)
-- 按成绩降序排序
SELECT stu.studentno as 学号,studentname as 学生姓名,subjectname as 科目名称,studentresult as 成绩
from student as stu INNER JOIN result as r
on stu.studentno=r.studentno
INNER JOIN `subject` sub
on r.subjectno=sub.subjectno
where subjectname='高等数学-3'
ORDER BY StudentResult DESC
分页
语法 : SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset
好处 : (用户体验,网络传输,查询压力)
推导:
第一页 : limit 0,3
第二页 : limit 3,3
第三页 : limit 6,3
…
第N页 : limit (pageNo-1)*pageSzie,pageSzie
[pageNo:页码,pageSize:单页面显示条数]
-- 每页显示3条数据
SELECT stu.studentno as 学号,studentname as 学生姓名,subjectname as 科目名称,studentresult as 成绩
from student as stu INNER JOIN result as r
on stu.studentno=r.studentno
INNER JOIN `subject` sub
on r.subjectno=sub.subjectno
where subjectname='高等数学-3'
ORDER BY StudentResult DESC,stu.studentno
LIMIT 0,3
-- 查询 高等数学-3 课程成绩前10名并且分数大于80的学生信息(学号,姓名,课程名,分数)
SELECT s.studentno,studentname,subjectname,StudentResult
FROM student s
INNER JOIN result r
ON r.studentno = s.studentno
INNER JOIN `subject` sub
ON r.subjectno = sub.subjectno
WHERE subjectname='高等数学-3' and studentresult>80
ORDER BY StudentResult DESC
LIMIT 0,10
4.6 子查询(和联表查询功能相似)
子查询
在查询语句中的WHERE条件子句中,又嵌套了另一个查询语句
嵌套查询可由多个子查询组成,求解的方式是由里及外;
子查询返回的结果一般都是集合,故而建议使用IN关键字;
-- 查询 高等数学-3 的所有考试结果(学号,科目编号,成绩),并且成绩降序排列
-- 方法一:使用连接查询
SELECT studentno,r.subjectno,StudentResult
FROM result r
INNER JOIN `subject` sub
ON r.`SubjectNo`=sub.`SubjectNo`
WHERE subjectname = '高等数学-3'
ORDER BY studentresult DESC;
-- 方法二:使用子查询(执行顺序:由里及外)
SELECT studentno,subjectno,StudentResult
FROM result
WHERE subjectno=(
SELECT subjectno FROM `subject`
WHERE subjectname = '高等数学-3'
)
ORDER BY studentresult DESC;
-- 查询课程为 高等数学-3 且分数不小于80分的学生的学号和姓名
-- 方法一:使用连接查询
SELECT s.studentno,studentname
FROM student s
INNER JOIN result r
ON s.`StudentNo` = r.`StudentNo`
INNER JOIN `subject` sub
ON sub.`SubjectNo` = r.`SubjectNo`
WHERE subjectname = '高等数学-3' AND StudentResult>=80
-- 方法二:使用连接查询+子查询
-- 分数不小于80分的学生的学号和姓名
SELECT r.studentno,studentname FROM student s
INNER JOIN result r ON s.`StudentNo`=r.`StudentNo`
WHERE StudentResult>=80
-- 在上面SQL基础上,添加需求:课程为 高等数学-2
SELECT r.studentno,studentname FROM student s
INNER JOIN result r ON s.`StudentNo`=r.`StudentNo`
WHERE StudentResult>=80 AND subjectno=(
SELECT subjectno FROM `subject`
WHERE subjectname = '高等数学-3'
)
-- 方法三:使用子查询
-- 分步写简单sql语句,然后将其嵌套起来
SELECT studentno,studentname FROM student WHERE studentno IN(
SELECT studentno FROM result WHERE StudentResult>=80 AND subjectno=(
SELECT subjectno FROM `subject` WHERE subjectname = '高等数学-3'
)
)
5 MySQL函数
5.1 常用函数(并不常用)
数据函数
-- 常用函数——数据函数
SELECT ABS(-8)
SELECT CEILING(9.4); /*向上取整*/
SELECT FLOOR(9.4); /*向下取整*/
SELECT RAND(); /*随机数,返回一个0-1之间的随机数[0,1)*/
SELECT SIGN(8); /*符号函数: 负数返回-1,正数返回1,0返回0*/
字符串函数
-- 常用函数——字符串函数
SELECT CHAR_LENGTH('狂神说坚持就能成功'); /*返回字符串包含的字符数*/
SELECT CONCAT('我','爱','程序'); /*合并字符串,参数可以有多个*/
SELECT INSERT('我爱编程helloworld',1,2,'超级热爱'); /*替换字符串,从某个位置开始替换某个长度*/
SELECT LOWER('KuangShen'); /*小写*/
SELECT UPPER('KuangShen'); /*大写*/
SELECT LEFT('hello,world',6); /*从左边截取*/
SELECT RIGHT('hello,world',5); /*从右边截取*/
SELECT REPLACE('狂神说坚持就能成功','坚持','努力'); /*替换字符串*/
SELECT SUBSTR('狂神说坚持就能成功',4,6); /*截取字符串,开始和长度*/
SELECT REVERSE('狂神说坚持就能成功'); /*反转*/
-- 查询姓王的同学,改成邹
SELECT REPLACE(studentname,'王','邹') AS 新名字
FROM student WHERE studentname LIKE '王%';
日期和时间函数(记住)
SELECT CURRENT_DATE(); /*获取当前日期*/
SELECT CURDATE(); /*获取当前日期*/
SELECT NOW(); /*获取当前日期和时间*/
SELECT LOCALTIME(); /*获取当前日期和时间,本地时间*/
SELECT SYSDATE(); /*获取当前日期和时间,系统时间*/
-- 获取年月日,时分秒
SELECT YEAR(NOW());
SELECT MONTH(NOW());
SELECT DAY(NOW());
SELECT HOUR(NOW());
SELECT MINUTE(NOW());
SELECT SECOND(NOW());
系统信息函数
SELECT VERSION(); /*版本*/
SELECT USER(); /*用户*/
SELECT SYSTEM_USER();
5.2 聚合函数(常用)
-- 聚合函数
/*COUNT:非空的*/
SELECT COUNT(studentname) FROM student;
SELECT COUNT(*) FROM student;
SELECT COUNT(1) FROM student; /*推荐*/
-- 从含义上讲,count(1) 与 count(*) 都表示对全部数据行的查询。
-- count(字段) 会统计该字段在表中出现的次数,忽略字段为null 的情况。即不统计字段为null 的记录。
-- count(*) 包括了所有的列,相当于行数,在统计结果的时候,包含字段为null 的记录;
-- count(1) 用1代表代码行,在统计结果的时候,包含字段为null 的记录 。
/*
很多人认为count(1)执行的效率会比count(*)高,原因是count(*)会存在全表扫描,而count(1)可以针对一个字段进行查询。其实不然,count(1)和count(*)都会对全表进行扫描,统计所有记录的条数,包括那些为null的记录,因此,它们的效率可以说是相差无几。而count(字段)则与前两者不同,它会统计该字段不为null的记录条数。
下面它们之间的一些对比:
1)在表没有主键时,count(1)比count(*)快
2)有主键时,主键作为计算条件,count(主键)效率最高;
3)若表格只有一个字段,则count(*)效率较高。
*/
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) AS 最高分,MIN(StudentResult) AS 最低分
FROM result AS r
INNER JOIN `subject` AS s
ON r.subjectno = s.subjectno
GROUP BY r.subjectno ---通过什么字段来分组
-- 筛选平均分大于80
SELECT subjectname,AVG(studentresult) AS 平均分,MAX(StudentResult) AS 最高分,MIN(StudentResult) AS 最低分
FROM result AS r
INNER JOIN `subject` AS s
ON r.subjectno = s.subjectno
GROUP BY r.subjectno -- 通过什么字段来分组
HAVING 平均分>80
5.3 数据库级别的MD5加密(扩展)
(1)MD5简介
MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。
(2)实现数据加密
-- 新建一个表 testmd5
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
-- 插入一些数据
INSERT INTO testmd5 VALUES(1,'kuangshen','123456'),(2,'qinjiang','456789'),(3,'王三','456779'),(4,'周三','556779'),(5,'周日','556789')
-- 如果我们要对pwd这一列数据进行加密,语法是:
update testmd5 set pwd = md5(pwd);
-- 如果单独对某个用户(如kuangshen)的密码加密:
INSERT INTO testmd5 VALUES(6,'kuangshen2','223456')
update testmd5 set pwd = md5(pwd) where name = 'kuangshen2';
-- 插入新的数据自动加密
INSERT INTO testmd5 VALUES(7,'kuangshen3',md5('123456'));
-- 查询登录用户信息(md5对比使用,查看用户输入加密后的密码进行比对)
SELECT * FROM testmd5 WHERE `name`='kuangshen3' AND pwd=MD5('123456');
6 事务
6.1 什么是事务?
6.2 实现
基本语法
-- 使用set语句来改变自动提交模式
SET autocommit = 0; /*关闭*/
SET autocommit = 1; /*开启*/
-- 注意:
--- 1.MySQL中默认是自动提交
--- 2.使用事务时应先关闭自动提交
-- 开始一个事务,标记事务的起始点
START TRANSACTION
-- 提交一个事务给数据库
COMMIT
-- 将事务回滚,数据回到本次事务的初始状态
ROLLBACK
-- 还原MySQL数据库的自动提交
SET autocommit =1;
-- 保存点
SAVEPOINT 保存点名称 -- 设置一个事务保存点
ROLLBACK TO SAVEPOINT 保存点名称 -- 回滚到保存点
RELEASE SAVEPOINT 保存点名称 -- 删除保存点
测试
/*
测试题目
A在线买一款价格为500元商品,网上银行转账.
A的银行卡余额为2000,然后给商家B支付500.
商家B一开始的银行卡余额为10000
创建数据库shop和创建表account并插入2条数据
*/
CREATE DATABASE `shop`CHARACTER SET utf8 COLLATE utf8_general_ci;
USE `shop`;
CREATE TABLE `account` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(32) NOT NULL,
`cash` DECIMAL(9,2) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO account (`name`,`cash`)
VALUES('A',2000.00),('B',10000.00)
-- 转账实现
SET autocommit = 0; -- 关闭自动提交
START TRANSACTION; -- 开始一个事务,标记事务的起始点
UPDATE account SET cash=cash-500 WHERE `name`='A';
UPDATE account SET cash=cash+500 WHERE `name`='B';
COMMIT; -- 提交事务
# rollback;
SET autocommit = 1; -- 恢复自动提交
7 索引
MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。提取句子主干,就可以得到。索引的本质:索引是数据结构。
7.1 索引的分类
作用:避免重复的列出现,唯一索引可以重复,多个列都可以标识位
默认的
/*
#方法一:创建表时
CREATE TABLE 表名 (
字段名1 数据类型 [完整性约束条件…],
字段名2 数据类型 [完整性约束条件…],
[UNIQUE | FULLTEXT | SPATIAL ] INDEX | KEY
[索引名] (字段名[(长度)] [ASC |DESC])
);
#方法二:CREATE在已存在的表上创建索引
CREATE [UNIQUE | FULLTEXT | SPATIAL ] INDEX 索引名
ON 表名 (字段名[(长度)] [ASC |DESC]) ;
#方法三:ALTER TABLE在已存在的表上创建索引
ALTER TABLE 表名 ADD [UNIQUE | FULLTEXT | SPATIAL ] INDEX
索引名 (字段名[(长度)] [ASC |DESC]) ;
#删除索引:DROP INDEX 索引名 ON 表名字;
#删除主键索引: ALTER TABLE 表名 DROP PRIMARY KEY;
#显示索引信息: SHOW INDEX FROM student;
*/
/*增加全文索引*/
ALTER TABLE `school`.`student` ADD FULLTEXT INDEX `studentname` (`StudentName`);
/*EXPLAIN : 分析SQL语句执行性能*/
EXPLAIN SELECT * FROM student WHERE studentno='1000';
/*使用全文索引*/
-- 全文搜索通过 MATCH() 函数完成。
-- 搜索字符串作为 against() 的参数被给定。搜索以忽略字母大小写的方式执行。对于表中的每个记录行,MATCH() 返回一个相关性值。即,在搜索字符串与记录行在 MATCH() 列表中指定的列的文本之间的相似性尺度。
EXPLAIN SELECT *FROM student WHERE MATCH(studentname) AGAINST('love');
/*
开始之前,先说一下全文索引的版本、存储引擎、数据类型的支持情况
MySQL 5.6 以前的版本,只有 MyISAM 存储引擎支持全文索引;
MySQL 5.6 及以后的版本,MyISAM 和 InnoDB 存储引擎均支持全文索引;
只有字段的数据类型为 char、varchar、text 及其系列才可以建全文索引。
测试或使用全文索引时,要先看一下自己的 MySQL 版本、存储引擎和数据类型是否支持全文索引。
*/
7.2 测试
DROP FUNCTION IF EXISTS mock_data;
DELIMITER $$ -- 写函数之前必须要写,标志
set global log_bin_trust_function_creators=1;
CREATE FUNCTION mock_data()
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), '24736743@qq.com', CONCAT('18', FLOOR(RAND()*(999999999-100000000)+100000000)),FLOOR(RAND()*2),UUID(), FLOOR(RAND()*100));
SET i = i + 1;
END WHILE;
RETURN i;
END;
SELECT mock_data();
SELECT * FROM app_user WHERE name = '用户9999'; -- 查看耗时
CREATE INDEX id_app_user_name ON app_user(name); -- 创建索引
索引在小数据量的时候,用处不大,但是在大数据的时候,区别十分明显。
7.3 索引原则
8 权限管理和备份
8.1 用户管理
基本命令
/* 用户和权限管理 */ ------------------
用户信息表:mysql.user
-- 刷新权限
FLUSH PRIVILEGES
-- 增加用户 CREATE USER kuangshen IDENTIFIED BY '123456'
CREATE USER 用户名 IDENTIFIED BY [PASSWORD] 密码(字符串)
- 必须拥有mysql数据库的全局CREATE USER权限,或拥有INSERT权限。
- 只能创建用户,不能赋予权限。
- 用户名,注意引号:如 'user_name'@'192.168.1.1'
- 密码也需引号,纯数字密码也要加引号
- 要在纯文本中指定密码,需忽略PASSWORD关键词。要把密码指定为由PASSWORD()函数返回的混编值,需包含关键字PASSWORD
-- 重命名用户 RENAME USER kuangshen TO kuangshen2
RENAME USER old_user TO new_user
-- 设置密码
SET PASSWORD = PASSWORD('密码') -- 为当前用户设置密码
SET PASSWORD FOR 用户名 = PASSWORD('密码') -- 为指定用户设置密码
-- 删除用户 DROP USER kuangshen2
DROP USER 用户名
-- 分配权限/添加用户
GRANT 权限列表 ON 表名 TO 用户名 [IDENTIFIED BY [PASSWORD] 'password']
- all privileges 表示所有权限
- *.* 表示所有库的所有表
- 库名.表名 表示某库下面的某表
-- 查看权限 SHOW GRANTS FOR root@localhost;
SHOW GRANTS FOR 用户名
-- 查看当前用户权限
SHOW GRANTS; 或 SHOW GRANTS FOR CURRENT_USER; 或 SHOW GRANTS FOR CURRENT_USER();
-- 撤消权限
REVOKE 权限列表 ON 表名 FROM 用户名
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 用户名 -- 撤销所有权限
权限解释
-- 权限列表
ALL [PRIVILEGES] -- 设置除GRANT OPTION之外的所有简单权限
ALTER -- 允许使用ALTER TABLE
ALTER ROUTINE -- 更改或取消已存储的子程序
CREATE -- 允许使用CREATE TABLE
CREATE ROUTINE -- 创建已存储的子程序
CREATE TEMPORARY TABLES -- 允许使用CREATE TEMPORARY TABLE
CREATE USER -- 允许使用CREATE USER, DROP USER, RENAME USER和REVOKE ALL PRIVILEGES。
CREATE VIEW -- 允许使用CREATE VIEW
DELETE -- 允许使用DELETE
DROP -- 允许使用DROP TABLE
EXECUTE -- 允许用户运行已存储的子程序
FILE -- 允许使用SELECT...INTO OUTFILE和LOAD DATA INFILE
INDEX -- 允许使用CREATE INDEX和DROP INDEX
INSERT -- 允许使用INSERT
LOCK TABLES -- 允许对您拥有SELECT权限的表使用LOCK TABLES
PROCESS -- 允许使用SHOW FULL PROCESSLIST
REFERENCES -- 未被实施
RELOAD -- 允许使用FLUSH
REPLICATION CLIENT -- 允许用户询问从属服务器或主服务器的地址
REPLICATION SLAVE -- 用于复制型从属服务器(从主服务器中读取二进制日志事件)
SELECT -- 允许使用SELECT
SHOW DATABASES -- 显示所有数据库
SHOW VIEW -- 允许使用SHOW CREATE VIEW
SHUTDOWN -- 允许使用mysqladmin shutdown
SUPER -- 允许使用CHANGE MASTER, KILL, PURGE MASTER LOGS和SET GLOBAL语句,mysqladmin debug命令;允许您连接(一次),即使已达到max_connections。
UPDATE -- 允许使用UPDATE
USAGE -- “无权限”的同义词
GRANT OPTION -- 允许授予权限
/* 表维护 */
-- 分析和存储表的关键字分布
ANALYZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE 表名 ...
-- 检查一个或多个表是否有错误
CHECK TABLE tbl_name [, tbl_name] ... [option] ...
option = {QUICK | FAST | MEDIUM | EXTENDED | CHANGED}
-- 整理数据文件的碎片
OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...
8.2 MySQL备份
数据库备份必要性
-
保证重要数据不丢失
-
数据转移
MySQL数据库备份方法
-
mysqldump备份工具
-
数据库管理工具,如SQLyog
-
直接拷贝数据库文件和相关配置文件
mysqldump客户端
作用 :
-
转储数据库
-
搜集数据库进行备份
-
将数据转移到另一个SQL服务器,不一定是MySQL服务器
-- 导出
1. 导出一张表 -- mysqldump -uroot -p123456 school student >D:/a.sql
mysqldump -u用户名 -p密码 库名 表名 > 文件名(D:/a.sql)
2. 导出多张表 -- mysqldump -uroot -p123456 school student result >D:/a.sql
mysqldump -u用户名 -p密码 库名 表1 表2 表3 > 文件名(D:/a.sql)
3. 导出所有表 -- mysqldump -uroot -p123456 school >D:/a.sql
mysqldump -u用户名 -p密码 库名 > 文件名(D:/a.sql)
4. 导出一个库 -- mysqldump -uroot -p123456 -B school >D:/a.sql
mysqldump -u用户名 -p密码 -B 库名 > 文件名(D:/a.sql)
可以-w携带备份条件
-- 导入
1. 在登录mysql的情况下:-- source D:/a.sql
source 备份文件
2. 在不登录的情况下
mysql -u用户名 -p密码 库名 < 备份文件
9 规范化数据库设计
9.1 为什么要设计数据库
当数据库比较复杂时我们需要设计数据库
9.2 三大范式(用来设计表)
10 JDBC(重点)
10.1 数据库驱动
我们的程序会通过数据库驱动,和数据库打交道。
10.2 JDBC
SUN公司为了简化开发人员的(对数据库的统一)操作,提供了一个(Java操作数据库的)规范,俗称JDBC这些规范的实现由具体的厂商去做~
10.3 第一个JDBC程序
import java.sql.*;
// 我的第一个jdbc程序
public class jdbcFirstDemo {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1. 加载驱动
Class.forName("com.mysql.cj.jdbc.Driver"); // 固定写法
//2. 用户信息和url
String url="jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT%2B8";
String username="root";
String password="******";
//3. 连接成功,数据库对象 Connection代表数据库
Connection connection = DriverManager.getConnection(url,username,password);
//4. 执行SQL的对象 Statement执行SQL的对象
Statement statement = connection.createStatement();
//5. 执行SQL的对象 去 执行SQL,可能存在结果,返回结果
String sql="select * from student";
ResultSet resultSet = statement.executeQuery(sql); //返回结果,结果集中封装了我们全部的查询出来的结果
while (resultSet.next()){
System.out.println("学号:"+resultSet.getObject("studentno"));
System.out.println("登录密码:"+resultSet.getObject("loginpwd"));
System.out.println("姓名:"+resultSet.getObject("studentname"));
System.out.println("性别:"+resultSet.getObject("sex"));
System.out.println("年级:"+resultSet.getObject("gradeid"));
System.out.println("手机号:"+resultSet.getObject("phone"));
System.out.println("出生日期:"+resultSet.getObject("borndate"));
System.out.println("身份证号:"+resultSet.getObject("identitycard"));
System.out.println("=================================================================");
}
//6. 释放连接
resultSet.close();
statement.close();
connection.close();
}
}
步骤总结:
- 加载驱动
- 连接数据库 DriverManager
- 获得执行sql的对象 Statement
- 获得返回的结果集
- 释放连接
DriverManager
Class.forName("com.mysql.cj.jdbc.Driver"); // 固定写法,加载驱动
Connection connection = DriverManager.getConnection(url,username,password);
// connection代表数据库
// 数据库设置自动提交
// 事务提交
// 事务回滚
connection.rollback();
connection.commit();
connection.setAutoCommit();
URL
String url="jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT%2B8";
//jdbc:mysql://主机地址:端口号:/数据库名?参数1&参数2&参数3
//mysql默认端口3306
Statement 执行SQL的对象 / PrepareStatement 执行SQL的对象
String sql="select * from student";
statement.executeQuery(); //查询操作返回ResultSet
statement.execute(); // 执行任何SQL
statement.executeUpdate();// 更新、插入、删除。都是用这个,返回一个受影响的行数
ResultSet查询的结果集:封装了所有的查询结果
获得指定的数据类型
resultSet.getObject();// 在不知道列类型的情况下使用
//如果知道列类型就使用指定的类型
resultSet.getString();
resultSet.getInt();
resultSet.getFloat();
resultSet.getDate();
...
遍历,指针
resultSet.beforeFirst();//移动到最前面
resultSet.afterLast();//移动到最后面
resultSet.next();//移动到下一个数据
resultSet.previous();//移动到前一行
resultSet.absolute(row); // 移动到指定行
释放资源
//6. 释放连接
resultSet.close();
statement.close();
connection.close();
10.4 statement对象
代码实现
1、提取工具类
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");
//1.驱动只用加载一次
Class.forName(driver);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, username, password);
}
//释放连接资源
public static void release(Connection conn, Statement st, ResultSet rs){
if(rs!=null){
try{
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(st!=null){
try{
st.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn!=null){
try{
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
2、编写增删改的方法,executeUpdate
(1)增
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 rs=null;
try {
conn = JdbcUtils.getConnection(); //获取数据库连接
st=conn.createStatement();//获得SQL的执行对象
String sql="INSERT INTO result(studentno,`subjectno`,examdate,studentresult)" +
"VALUES(1011,5,null,99)";
int i = st.executeUpdate(sql);
if(i>0){
System.out.println("插入成功!");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
(2)删
import JDBCDemo02.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 rs=null;
try {
conn = JdbcUtils.getConnection(); //获取数据库连接
st=conn.createStatement();//获得SQL的执行对象
String sql="DELETE FROM result WHERE studentno=1010";
int i = st.executeUpdate(sql);
if(i>0){
System.out.println("删除成功!");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
(3)改
import JDBCDemo02.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 rs=null;
try {
conn = JdbcUtils.getConnection(); //获取数据库连接
st=conn.createStatement();//获得SQL的执行对象
String sql="UPDATE result SET studentresult=45 WHERE studentno=1003";
int i = st.executeUpdate(sql);
if(i>0){
System.out.println("更新成功!");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
(4)查 executeQuery()
import JDBCDemo02.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 rs=null;
try {
conn = JdbcUtils.getConnection(); //获取数据库连接
st=conn.createStatement();//获得SQL的执行对象
String sql="select * from result where studentno=1000";
rs = st.executeQuery(sql);
while (rs.next()){
System.out.println("考试时间:"+rs.getDate("examdate"));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
SQL注入问题
sql存在漏铜,会被攻击导致数据泄露,SQL会被拼接 or
10.5 PreparedStatement对象
PreparedStatement 防止SQL注入的本质,把传递进来的参数当做字符
假设其中存在转义字符,就直接忽略,’ 会被直接转义
import JDBCDemo02.utils.JdbcUtils;
import java.sql.PreparedStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
public class PreparedStatement_Select {
public static void main(String[] args) {
Connection conn=null;
PreparedStatement st=null;
ResultSet rs= null;
try {
conn=JdbcUtils.getConnection();
String sql="select * from result where studentno=?"; //编写SQL
st= conn.prepareStatement(sql); //预编译
st.setInt(1,1005);//传递参数
rs=st.executeQuery();//执行
if(rs.next()){
System.out.println("分数:"+rs.getInt("studentresult"));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
10.6 idea连接数据库
10.7 事务
import JDBCDemo02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestTransaction {
public static void main(String[] args) {
Connection conn=null;
PreparedStatement st=null;
ResultSet rs=null;
try {
conn=JdbcUtils.getConnection();
//关闭数据库的自动提交,自动会开启事务
conn.setAutoCommit(false); //开启事务
String sql1="update account set money = money-100 where name1='A'";
st=conn.prepareStatement(sql1);
st.executeUpdate();
// int x=1/0; //报错
String sql2="update account set money = money+100 where name1='B'";
st=conn.prepareStatement(sql2);
st.executeUpdate();
//业务完毕,提交事务
conn.commit();
System.out.println("事务提交成功!");
} catch (SQLException e) {
try {
conn.rollback(); //如果失败则回滚事务
} catch (SQLException throwables) {
throwables.printStackTrace();
}
e.printStackTrace();
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
10.8 数据库连接池
DBCP
//JdbcUtils_DBCP
import org.apache.commons.dbcp2.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
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("dbcpconfig.properties");
Properties properties = new Properties();
properties.load(in);
//创建数据源 工厂模式--> 创建
dataSource= BasicDataSourceFactory.createDataSource(properties);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection() throws SQLException {
return dataSource.getConnection(); //从数据源中获取连接
}
//释放连接资源
public static void release(Connection conn, Statement st, ResultSet rs){
if(rs!=null){
try{
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(st!=null){
try{
st.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn!=null){
try{
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
//Test_DBCP
import JDBCDemo02.DBCP.utils.JdbcUtils_DBCP;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestDBCP {
public static void main(String[] args) {
Connection conn=null;
Statement st=null;
ResultSet rs=null;
try {
conn = JdbcUtils_DBCP.getConnection(); //获取数据库连接
st=conn.createStatement();//获得SQL的执行对象
String sql="INSERT INTO result(studentno,`subjectno`,examdate,studentresult)" +
"VALUES(1012,5,null,100)";
int i = st.executeUpdate(sql);
if(i>0){
System.out.println("插入成功!");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JdbcUtils_DBCP.release(conn,st,null);
}
}
}
c3p0