JavaEE:企业级Java开发 Web
前端(页面:展示,数据!)
后端(连接点:连接数据库JDBC,链接前端(控制,控制视图跳转,和给前端传递数据))
数据库(存数据,txt,Excel,word)
只会写代码,学好数据库,基本混饭吃!
操作系统,数据结构与算法!当一个不错的程序猿!
离散数学,数字电路,体系结构,编译原理。+实战经验,高级程序员~优秀的程序猿
1、岗位需求
2、现在的世界,大数据时代~,得数据库者得天下。
3、被迫需求: 存数据
4、数据库是所有软件体系中最核心的存在 DBA
数据库(DB,DataBase)
概念:数据仓库,软件,安装在操作系统(windows、linux、mac…)之上!SQL,可以存储大量的数据。500万!
作用:存储数据,管理数据
关系型数据库:SQL
非关系型数据库:NoSQL(Not Only)
DBMS(数据库管理系统)
MySQL是一个关系型数据库管理系统
前世: 瑞典MySQL AB 公司
今生: 属于 Oracle 旗下产品
MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。
开源的数据库软件~
体积小、速度快、总体拥有成本低。招人成本比较低,所有人必须会~
中小型网站、或者大型网站,集群!
官网:https://www.mysql.com
现在用的最多的5.7,比较稳定,8.0最新版
安装教程https://blog.csdn.net/weixin_45277249/article/details/114202833
打开MySQL命令窗口
连接数据库语句 : mysql -h 服务器主机地址 -u 用户名 -p 用户密码
注意 : -p后面不能加空格,否则会被当做密码的内容,导致登录失败 !本机操作可省略-h参数
查看MySQL版本信息和用户名:select version(),user();
version()返回MySQL版本号,user()返回连接数据库的用户名
几个基本的数据库操作命令 :
展示所有数据库
show databases;
切换到某个数据库
use 数据库名;
查看数据库下所有表
show tables;
退出mysql
exit;
刷新数据库
flush privileges;
显示表mysql数据库中user表的列信息
describe user;
修改密码
update user set password=password('123456')where user='root';
以数据库为基本单位 : 系统数据库 用户数据库
以数据表 (table) 为基本单位
DML数据操作语言(Data Manipulation Language):用来操作数据库中所包含的数据
DDL数据定义语言(Data definition Language) :用于创建和删除数据库对象等操作
DQL数据查询语言(Data Query Language) :用来对数据库中的数据进行查询
DCL数据控制语言(Data Control Language):用来控制数据库组件的存取许可、存取权限等
带了 [ ] 就是可选的
创建数据库
create database [if not exists] 数据库名;-- if not exists意思是如果不存在则创建
查看数据库列表
show databases;-- 该列表中会有四个系统数据库和自己建的数据库
使用数据库
use `school`;-- 如果你的表名或字段名是一个特殊字符,就需要带反引号
删除数据库
drop database [if exists] 数据库名;
注意:以分号作为一条命令的结束符,Windows系统下默认不区分大小写
数值
类型 | 说明 | 取值范围 | 存储需求 |
---|---|---|---|
TINYINT | 非常小的数据 | 有符值: -27 ~ 27-1 无符号值:0 ~ 28-1 | 1字节 |
SMALLINT | 较小的数据 | 有符值: -215 ~ 215-1 无符号值: 0 ~ 216-1 | 2字节 |
MEDIUMINT | 中等大小的数据 | 有符值: -223 ~ 223-1 无符号值: 0 ~ 224-1 | 3字节 |
INT | 标准整数 | 有符值: -231 ~ 231-1 无符号值:0 ~ 232-1 | 4字节 |
BIGINT | 较大的整数 | 有符值: -263 ~263-1 无符号值:0 ~264-1 | 8字节 |
FLOAT | 单精度浮点数 | ±1.1754351e -38 | 4字节 |
DOUBLE -> java double | 双精度浮点数 | ±2.2250738585072014e -308 | 8字节 |
DECIMAL | 字符串形式的浮点数 | Decimal(M,D) | M+2个字节 |
字符串
字符串类型 | 说明 | 长度 |
---|---|---|
CHAR[(M)] | 定长字符串 | M字节 |
VARCHAR[(M)] | 可变字符串 | 可变长度 |
TINYTEXT | 微型文本串 | 0~28–1字节 |
TEXT | 文本串 | 0~216–1字节 |
VARCHAR相对于Java的String
日期类型
日期类型 | 格式 | 取值范围 |
---|---|---|
DATE | YYYY-MM-DD,日期格式 | 1000-01-01~ 9999-12-31 年月日 |
DATETIME | YY-MM-DD hh:mm:ss: | 1000-01-01 00:00:00 ~9999-12-31 23:59:59 年月日时分秒 |
TIME | hh:mm:ss: | -835:59:59 ~ 838:59:59 |
TIMESTAMP | YYYYMMDDHHMMSS | 1970年某时刻~2038年某时刻,精度为1秒 |
YEAR | YYYY格式的年份 | 1901~2155 |
null
【注意】不要使用NULL进行运算,结果为NULL
UNSIGNED:设置该列不可出现负数
ZEROFILL: 不足位数 0 填充 ,设定向这属性该列自动会有 UNSIGEND
UNIQUE KEY(UK): 唯一约束,设置字段的值是唯一的 允许为空,但只能有一个空值
PRIMARY KEY(PK):设置主键,就是能够唯一标识某个数据表数据的列,只要设置为主键 该列必须是非空 且唯一
FOREIGN KEY(FK) :用于在两表之间建立关系,需要指定引用主表的哪一字段
auto_increment:自动增长,在上一条记录的基础上+1(默认),可以自定义主键自增的起始值和步长
NOT NULL: 标识该列不许为空
DEFAULT :设置默认值
COMMENT :给列或表加注释
创建数据表
CREATE TABLE [IF NOT EXISTS] `表名`(
`字段名` 列类型 [属性] [索引] [注释],
`字段名` 列类型 [属性] [索引] [注释],
……
`字段名` 列类型 [属性] [索引] [注释],
)[表类型] [字符集设置] [注释]
create table [IF NOT EXISTS] `user`(
id INT PRIMARY KEY AUTO_INCREMENT COMMENT '编号',
username VARCHAR(25) not null COMMENT '姓名',
gender VARCHAR(2) DEFAULT '男' not NULL
)COMMENT '用户表';
【注意】使用英文括号,表名和字段名尽量使用反引号括起来
删除数据表
drop TABLE [IF EXISTS] `表名`;
常用命令
SHOW CREATE DATABASE `user` -- 查看创建数据库的语句
SHOW CREATE TABLE `user` -- 查看student数据表的定义语句
-- 显示表的结构
DESC `user`
DESCRIBE `uer`
名称 | InnoDB | MyISAM |
---|---|---|
事务处理 | 支持 | 不支持 |
数据行锁定 | 支持 | 不支持 |
外键约束 | 支持 | 不支持 |
全文索引 | 不支持 | 支持 |
表空间大小 | 较大,约MyISAM的2倍 | 较小 |
适用场合
在物理空间存在的位置
MySQL引擎在物理文件上的区别
设置数据库表的字符集编码
CHARSET=utf8
不设置的话,会是mysql默认的字符集编码~(不支持中文!)
MySQL的默认编码是Latin1,不支持中文
在my.ini中配置默认的编码
character-set-server=utf8
修改表名
ALTER TABLE `旧名` rename `新名`;
添加字段
ALTER TABLE `表名` ADD 字段名 列属性;
修改表的字段
ALTER TABLE `表名` MODIFY 字段名 列属性;-- 修改约束,不改名,重新设定
ALTER TABLE `表名` CHANGE 旧字段名 新字段名 列属性;-- 字段重命名
删除表的字段
ALTER TABLE `表名` drop `字段名`
删除数据表
drop TABLE [IF EXISTS] `表名`;
所有的创建和删除操作尽量加上判断,以免报错~
【注意点】
类型 | 符号 |
---|---|
算术运算符 | + 加 -减 *乘 / 除 %取余 |
赋值运算符 | = |
比较/关系运算符 | = 判断相等 > 大于 <小于 >=大于等于 <=小于等于 <> 或 != 不等于 |
逻辑运算符 | and并且(&&) or或者(||) not非(取反) |
between | 某个区间,between 2 and 5 (2 - 5之间) |
外键:一张表里的某个字段引用着另一张表里的某个字段信息.(==外键可以保证数据的合理性和完整一致性)
【注意】
ALTER TABLE student
ADD CONSTRAINT fk_student_grade
FOREIGN KEY (gradeid)
REFERENCES grade(id);
ALTER TABLE student drop FOREIGN KEY fk_student_grade
以上的操作都是物理外键,数据库级别的外键,我们不建议使用!(避免数据库过多造成困扰)
最佳实践
数据库意义:数据存储,数据管理
语法
INSERT INTO 表名 列名 VALUES 值列表
插入一条数据
INSERT INTO student(studentNo,studentName`password`,gradeid,sex,phone,address,borthday,email,card)
VALUES
(null,'小明','123123',1,'男','123123123','北京','2001-1-1','[email protected]','9999999');
插入多条数据
-- id设置了自增,可以省略不写
insert into grade (id,gradeName)
VALUES('s1'),('s2'),('y2');
【注意】
语法
update 表名 SET 列名 = 更新值 [WHERE 更新条件]
修改一个字段
update `student` SET `name`='小明' WHERE id=1;
修改多个字段
update `student` SET `name`='小明',age=17 WHERE id=1;
多个条件
update `student` SET `name`='小明' WHERE id=1 AND age=1
修改一个区间的数据
update `student` SET `name`='小明' WHERE id<5
【注意】
语法
DELETE FROM 表名 [WHERE 删除条件]
删除指定数据
delete from `student` WHERE id =1
作用:完全清空一个数据库表,表的结构和索引约束不会变!
-- TRUNCATE TABLE 表名
TRUNCATE TABLE `student`
了解即可:delete删除的问题,重启数据库,现象
Data Query Language:数据查询语言
select * from `表名`;-- *代表全部列
select `字段1`,`字段2`,`字段n` from `表名`;-- 语法
------------------------------------------------
select `name`,`age` from `student`;
AS
关键字,可以给字段起别名,也可以给表起别名字段名 AS 别名
select `字段1` AS 别名1,`字段2` AS 别名2 from `表名` AS别名; -- 语法
-----------------------------------------------------------------
select `name` AS 姓名,`age` AS 年龄 from `student` AS s;
select CONCAT('姓名:',name) from student;
select distinct `StudentNo` from `student`;
表达式
from 表名SELECT VERSION() -- 查询mysql版本(函数)
SELECT 100*3-1 AS 计算结果 -- 用来计算(表达式)
SELECT @@auto_increment_increment -- 查询自增的步长(变量)
--------------------------------------------------------
-- 学员考试成绩 +1分查看
SELECT StudentNo,StudentResult + 1 AS '提分后' FROM result
运算符 | 语法 | 描述 |
---|---|---|
and && | a and b a&&b | 并且,两个都为真,结果为真 |
or || | a or b a||b | 或,其中一个为真,结果为真 |
not ! | not a !a | 逻辑非,真为假,假为真! |
-- 查询考试成绩在95-100分之间
SELECT studentNo,StudentResult FROM result
WHERE StudentResult>=95 AND StudentResult<=100
-- 模糊查询(区间)
SELECT studentNo,StudentResult FROM result
WHERE StudentResult BETWEEN 95 AND 100
-- 除了1000号学生之外的成绩
SELECT studentNo,StudentResult FROM result
WHERE NOT studentNo = 1000
运算符 | 语法 | 描述 |
---|---|---|
IS NULL | a is null | 如果操作符为NULL,结果为真 |
IS NOT NULL | a is not null | 如果操作符不为NULL,结果为真 |
BERWEEN | a between b and c | 若a在b和c之间,则结果为真 |
LIKE | a like b | SQL匹配,如果a匹配b,则结果为真 |
IN | a in (a1,a2,a3……) | 假设a在a1或者a2……其中的某一个值中,结果为真 |
==============LIKE模糊查询====================
-- 查询姓刘的同学 %代表任意字符
SELECT StudentNo,StudentName FROM student
WHERE StudentName LIKE '刘%'
-- 查询姓刘的同学,名字后面只有一个字符
SELECT StudentNo,StudentName FROM student
WHERE StudentName LIKE '刘_'
-- 查询名字中间有 “明”的同学
SELECT StudentNo,StudentName FROM student
WHERE StudentName LIKE '%明%'
=========in(具体的一个或多个值)==============
-- 查询 1001,1002,1003号学员
SELECT StudentNo,StudentName FROM student
WHERE StudentNo IN(1001,1002,1003)
-- 查询在北京的学生
SELECT StudentNo,StudentName FROM student
WHERE address IN(北京)
=============null not null=================
-- 查询地址为空的学生 null ''
SELECT StudentNo,StudentName FROM student
WHERE address='' OR address IS NULL
-- 查询有出生日期的同学 不为空
SELECT StudentNo,StudentName FROM student
WHERE birndate IS NOT NULL
完整的查询语法
select [select选项] 字段列表[字段别名] from 数据源
[where 字句] [group by子句 ] [having 子句] [order by 子句] [limit 子句];
参考文章https://blog.csdn.net/u011991249/article/details/64519945
==================INNER JOIN======================
-- 查询参加了考试的同学(学号,姓名,科目编号,分数)
SELECT * FROM student
SELECT * FROM result
/*
思路
1.分析需求,分析查询的字段来自哪些表(连接查询)
2.确定使用哪种连接查询?七种
确定交叉点(两个表中哪个数据是相同的)
判断的条件:学生表中的 studentNo = 成绩表中的 studentNo
*/
-- join(连接的表) on(判断的条件) 连接查询
-- where等值查询
SELECT s.studentNo,studentName,SubjectNo,StudentResult
FROM stdent AS s
INNER JOIN result AS r
WHERE s.studentNo=r.studentNo
-- Right JOIN
SELECT s.studentNo,studentName,SubjectNo,StudentResult
FROM stdent s
RIGHT JOIN result r
ON s.studentNo=r.studentNo
-- Left JOIN
SELECT s.studentNo,studentName,SubjectNo,StudentResult
FROM stdent s
LEFT JOIN result r
ON s.studentNo=r.studentNo
-- 查询缺考的同学
SELECT s.studentNo,studentName,SubjectNo,StudentResult
FROM stdent s
LEFT JOIN result r
ON s.studentNo=r.studentNo
WHERE StudentResult IS NULL
-- 查询参加了考试的同学信息:学号,学生姓名,科目名,分数
/*
思路
1.分析需求,分析查询的字段来自哪些表,studnet、result、subject(连接查询)
2.确定使用哪种连接查询?七种
确定交叉点(两个表中哪个数据是相同的)
判断的条件:学生表中的 studentNo = 成绩表中的 studentNo
*/
SELECT s.studentNo,studentName,SubjectNo,StudentResult
FROM stdent s
RIGHT JOIN result r
ON s.studentNo=r.studentNo
INNER JOIN `subject` sub
ON r.studentNo=sub.SubjectNo
操作 | 描述 |
---|---|
Inner join | 如果表中至少有一个匹配,就返回行 |
left join | 会从左表中返回所有的值,即使右表中没有匹配 |
right join | 会从右表中返回所有的值,即使左表中没有匹配 |
a LEFT JOIN b -- 在左边就是左表
FROM 表 xxx join 连接的表 on 交叉条件
自连接是内连接的一种,内连接可分为等值连接和自身连接。
等值连接:查找两个表中连接字段相等的记录。
自身连接: 就是和自己进行连接查询,给一张表取两个不同的别名,然后附上连接条件。
现在我们有一张category表
categoryid | pid | categoryName |
---|---|---|
2 | 1 | 信息技术 |
3 | 1 | 软件开发 |
4 | 3 | 数据库 |
5 | 1 | 美术设计 |
6 | 3 | web开发 |
7 | 2 | 办公信息 |
8 | 5 | ps技术 |
我们把上表拆分成两张表来看
categoryid | categoryName |
---|---|
2 | 信息技术 |
3 | 软件开发 |
5 | 美术设计 |
pid | categoryName |
---|---|
3 | 数据库 |
2 | 办公信息 |
3 | web开发 |
5 | 美术设计 |
操作:查询父类对应的子类
-- 把一张表看成两张一模一样的表
SELECT a.categoryName AS '父栏目',b.categoryName AS '子栏目'
FROM category AS a,category AS b
WHERE a.categoryid = b.pid
结果如下:
父栏目 | 子栏目 |
---|---|
信息技术 | 办公信息 |
软件开发 | 数据库 |
软件开发 | web开发 |
美术设计 | ps技术 |
下面这个例子来自https://www.zhihu.com/question/290782386
以下面这张表为例:
要查询与姓名 HH 同龄且籍贯也相同的学生信息。就可以用自连接查询:
SELECT B.学号, B.姓名, B.性别, B.籍贯, B.年龄
FROM student A
JOIN student B
ON A.年龄=B.年龄 AND A.籍贯=B.籍贯 AND A.姓名='HH'
结果如下:
ORDER BY
,后面跟的字段就是以它排序desc
由大到小asc
由小到大select * from result ORDER BY StudentResult asc; -- 升序
select * from result ORDER BY StudentResult desc;-- 降序
为什么要分页?假设你有100万条数据
LIMIT 起始值,pageSize
-- 起始值是从第几条数据开始
-- pageSize是页面大小,也就是每页显示多少条数据
起始值 = (当前页-1)*页面大小
数据总数 / 页面大小 = 总页数
-- 第一页
select * from `subject` LIMIT 0,5; -- (1-1)*5
-- 第二页
select * from `subject` LIMIT 5,5; -- (2-1)*5
-- 第三页
select * from `subject` LIMIT 10,5; -- (3-1)*5
-- 第n页
select * from `subject` LIMIT (n-1)*5,pageSize; -- (n-1)*pageSize,pageSize
where (这个值是计算出来的)
本质:在where语句中嵌套一个子查询语句
where(select *from)
-- 方式一:使用连接查询
SELECT `studentNo`,`SubjectName`,`StudentResult`
FROM `result` r
INNER JOIN `subject`sub
ON r.SubjectNo = sub.SubjectNo
WHERE SubjectName = '数据库结构-1'
ORDER BY StudentResult DESC
-- 方式二:使用子查询()
SELECT `studentNo`,`SubjectName`,`StudentResult`
FROM `result`
WHERE SubjectNo = (
-- 查询所有 数据库结构-1 的学生学号
SELECT SubjectNo FROM `subject` WHERE SubjectName = '数据库结构-1'
)
ORDER BY StudentResult DESC
SELECT s.`StudentNo`,`SudentName`
FROM student s
INNER JOIN result r
ON r.StudentNo = s.StudentNo
WHERE `StudentResult` >= 80
SELECT s.`StudentNo`,`SudentName`
FROM student s
INNER JOIN result r
ON r.StudentNo = s.StudentNo
WHERE `StudentResult` >= 80 AND `SubjectNo` = (
SELECT SubjectNo FROM `subject` WHERE `SubjectName` = '高等数学-2'
)
-- 方式一:连接查询
SELECT s.`StudentNo`,`SudentName`
FROM student s
INNER JOIN result r
ON s.StudentNo = r.StudentNo
INNER JOIN `subject` sub
ON r.`SubjectNo` = sub.SubjectNo
WHERE `SubjectName`='高等数学-2' AND StudentResult>=80
-- 方式二:嵌套子查询
SELECT `StudentNo`,`SudentName` FROM student WHERE StudentNo IN(
SELECT StudentNo FROM result WHERE StudentResult>80 AND SubjectNo=(
SELECT SubjectNo FROM `subject` WHERE `SubjectName` = '高等数学-2'
)
)
-- 查询不同课程的平均分,最高分,最低分,平均分大于80
-- 根据不同课程分组(要点)
SELECT SubjectName,AVG(StudentResult) AS 平均分,Max(StudentResult) AS 最高分,MIN(StudentResult) AS 最低分
FROM result r
INNER JOIN `subject` sub
ON r.SubjectNo = sub.SubjectNo
GROUP BY r.SubjectNo -- 通过什么字段来分组
HAVING 平均分 > 80
官网地址:https://dev.mysql.com/doc/refman/5.7/en/sql-function-reference.html
数学运算
SELECT ABS(-8) -- 绝对值
SELECT CEILING(9.4) -- 向上取整
SELECT FLOOR(9.4) -- 向下取整
SELECT RAND() -- 返回一个0~1之间的随机数
SELECT SIGN(-10) -- 判断一个数的符号 0返回0 负数返回-1 正数返回1
字符串函数
SELECT CHAR_LENGTH('即使再小的帆也能远航') -- 字符串长度
SELECT CONCAT('你','好','mysql') -- 拼接字符串
SELECT INSERT('我爱编程',1,2,'超级热爱') -- 查询,从某个位置开始替换某个长度
SELECT LOWER('Chen') -- 小写字符
SELECT UPPER('Chen') -- 大小字符
SELECT INSTR('Chen','C') -- 返回第一次出现字符串的索引
SELECT REPLACE('坚持就能成功','坚持','努力')-- 替换出现的指定字符
SELECT SUBSTRING('坚持就能成功',5,6) -- 返回指定的子字符串
SELECT REVERSE('害历好') -- 反转
时间和日期
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 SYSTEM_USER() -- 系统当前用户
SELECT USER() -- 系统当前用户
SELECT VERSION() -- 当前版本
函数名称 | 描述 |
---|---|
COUNT() | 计数 |
SUM() | 求和 |
AVG() | 平均值 |
MAX() | 最大值 |
MIN() | 最小值 |
-- 都能够统计表中的数据(想查询一个表中有多少条记录,就使用count())
SELECT COUNT(studentname) FROM student; -- COUNT(字段),会忽略所有null值
SELECT COUNT(*) FROM student; -- COUNT(*),不会忽略null值
SELECT COUNT(1) FROM result; -- COUNT(1),不会忽略null值
SELECT SUM(`StudentResult`) AS 总和 FROM result
SELECT AVG(`StudentResult`) AS 平均分 FROM result
SELECT MAX(`StudentResult`) AS 最高分 FROM result
SELECT MIN(`StudentResult`) AS 最低分 FROM result
事务(Transaction)是指将一系列数据操作捆绑成为一个整体进行统一管理。
如果某一事务执行成功,则在该事务中进行的所有数据更改均会提交,成为数据库的永久组成部分
如果事务执行时遇到错误且必须取消或回滚,则数据将全部恢复到操作前的状态,所有数据的更改均被消除
下面是一个转账操作
A有1000元,B有200元
1、SQL执行 A 给 B 转账200元
2、SQL执行 B 收到 A 的钱
最后 A有800元,B有400元
上面的转账操作,A的钱转出去了,而程序执行到这里出错,B没有收到钱,那钱不就丢了,这个时候事务的作用来了
一个事务的所有系列操作步骤被看成一个动作,所有的步骤要么全部完成,要么一个也不会完成。
如果在事务过程中发生错误,则会回滚到事务开始前的状态,将要被改变的数据库记录不会被改变。
一致性是指在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏,即数据库事务不能破坏关系数据的完整性及业务逻辑上的一致性。
主要用于实现并发控制,隔离能够确保并发执行的事务按顺序一个接一个地执行。
通过隔离,一个未完成事务不会影响另外一个未完成事务。
一旦一个事务被提交,它应该持久保存,不会因为与其他操作冲突而取消这个事务。
隔离所导致的一些问题
脏读:
指一个事务读取了另外一个事务未提交的数据。
不可重复读:
在一个事务内读取表中的某一行数据,多次读取结果不同。(这个不一定是错误,只是某些场合不对)
虚读(幻读):
是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。(一般是行影响,多了一行)
-- mysql 是默认开启的事务自动提交的
-- 关闭自动提交后,从下一条SQL语句开始则开启新事务,需使用COMMIT或ROLLBACK语句结束该事务
SET autocommit = 0 -- 关闭
SET autocommit = 1 -- 开启(默认的)
-- 手动处理事务
-- 事务开启 或 BEGIN;
START TRANSACTION -- 标记一个事务的开始,从这个之后的 sql 都在同一个事务内
INSERT xxx
INSERT xxx
-- 提交:持久化
COMMIT
-- 回滚:回到原来的样子(失败!)
ROLLBACK
-- 事务结束
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; -- 恢复自动提交
MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。提取句子主干,就可以得到索引的本质:索引是数据结构。
在一个表中,主键索引只能有一个,唯一索引可以有多个
-- 索引的使用
-- 1、在创建表的时候给字段增加索引
-- 2、创建完毕后,增加索引
-- 显示所有的索引信息
SHOW INDEX FROM student
-- 增加一个全文索引(索引名,列名)
ALTER TABLE school.student ADD FULLTEXT INDEX studentName(studentName)
-- 删除索引
DROP INDEX index_name ON table_name;
-- EXPLAIN 分析sql执行的状况
EXPLAIN SELECT * FROM student;-- 非全文索引
SELECT * FROM student WHERE MATCH(studentName) AGAINST('刘');
参考文章https://mp.weixin.qq.com/s/-_-fRKNOi5rI6tb8RINZ0Q
建表app_user:
CREATE TABLE `app_user` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT '' COMMENT '用户昵称',
`email` varchar(50) NOT NULL COMMENT '用户邮箱',
`phone` varchar(20) DEFAULT '' COMMENT '手机号',
`gender` tinyint(4) unsigned DEFAULT '0' COMMENT '性别(0:男;1:女)',
`password` varchar(100) NOT NULL COMMENT '密码',
`age` tinyint(4) DEFAULT '0' COMMENT '年龄',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='app用户表'
批量插入数据:100w条
DROP FUNCTION IF EXISTS mock_data;
DELIMITER $$
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), '[email protected]', 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'; -- 查看耗时
SELECT * FROM app_user WHERE name = '用户9999';
SELECT * FROM app_user WHERE name = '用户9999';
mysql> EXPLAIN SELECT * FROM app_user WHERE name = '用户9999'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: app_user
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 992759
filtered: 10.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)
创建索引
CREATE INDEX idx_app_user_name ON app_user(name);
测试普通索引
mysql> EXPLAIN SELECT * FROM app_user WHERE name = '用户9999'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: app_user
partitions: NULL
type: ref
possible_keys: idx_app_user_name
key: idx_app_user_name
key_len: 203
ref: const
rows: 1
filtered: 100.00
Extra: NULL
1 row in set, 1 warning (0.00 sec)
mysql> SELECT * FROM app_user WHERE name = '用户9999';
1 row in set (0.00 sec)
mysql> SELECT * FROM app_user WHERE name = '用户9999';
1 row in set (0.00 sec)
mysql> SELECT * FROM app_user WHERE name = '用户9999';
1 row in set (0.00 sec)
索引在小数据量的时候,用处不大,但是在大数据量的时候,区别十分明显~
Hash类型的索引
Btree:InnoDB的默认数据结构
建议阅读: http://blog.codinglabs.org/articles/theory-of-mysql-index.html
原文链接:https://mp.weixin.qq.com/s/dCt_v5KQCTpgBdlY__0BSA
使用SQLyog 创建用户,并授予权限演示
创建用户
-- CREATE USER 用户名 IDENTIFIED BY [PASSWORD] 密码(字符串)
CREATE USER cgz IDENTIFIED BY '123456'
【注意】
修改密码
-- 修改当前用户密码
SET PASSWORD = PASSWORD('密码')
-- 修改指定用户密码
SET PASSWORD FOR 用户名 = PASSWORD('密码')
重命名用户
-- RENAME USER old_user TO new_user
RENAME USER cgz TO cgz2
用户权限
-- GRANT 权限列表 ON 表名 TO 用户名 [IDENTIFIED BY [PASSWORD] 'password']
GRANT all privileges ON *.* TO cgz2
all privileges
表示所有权限*.*
表示所有库的所有表库名.表名
表示某库下面的某表查看权限
-- SHOW GRANTS FOR 用户名
SHOW GRANTS FOR root@localhost; -- 查看指定用户权限
-- 查看当前用户权限
SHOW GRANTS;
-- 或
SHOW GRANTS FOR CURRENT_USER;
-- 或
SHOW GRANTS FOR CURRENT_USER();
撤销权限
-- REVOKE 权限列表 ON 表名 FROM 用户名
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 用户名 -- 撤销所有权限
删除用户
-- DROP USER 用户名
DROP USER cgz2
刷新权限
FLUSH PRIVILEGES
-- 权限列表
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] ...
数据库备份必要性
MySQL数据库备份方法
mysqldump客户端
作用 :
-- mysqldump -u用户名 -p密码 库名 表名 > 文件名(D:/a.sql)
mysqldump -uroot -p123456 school student >D:/a.sql
-- mysqldump -u用户名 -p密码 库名 表1 表2 表3 > 文件名(D:/a.sql)
mysqldump -uroot -p123456 school student result >D:/a.sql
-- mysqldump -u用户名 -p密码 库名 > 文件名(D:/a.sql)
mysqldump -uroot -p123456 school >D:/a.sql
-- mysqldump -u用户名 -p密码 -B 库名 > 文件名(D:/a.sql)
mysqldump -uroot -p123456 -B school >D:/a.sql
-- 在登录mysql的情况下:source 备份文件
source D:/a.sql
-- 在不登录的情况下
mysql -u用户名 -p密码 库名 < 备份文件
当数据库比较复杂的时候,我们就需要设计了
糟糕的数据库数据:
良好的数据库设计:
软件开发中,关于数据库设计
设计数据库的步骤:(个人博客)
收集信息,分析需求
标识实体(把需求落地到每个字段)
标识实体 之间的关系
为什么需要数据规范化?
参考文章:https://www.cnblogs.com/wsg25/p/9615100.html
第一范式(1NF)
原子性:保证每一列不可再分
第二范式(2NF)
前提:满足第一范式
每张表只描述一件事情
第三范式(3NF)
前提:满足第一范式和第二范式
第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。
(规范数据库的设计)
关联查询的表不得超过三张表