MySQL

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密码 库名 表123 > 文件名(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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值