数据库学习之MySQL

MySQL简介

数据库

为什么要学数据库?

有以下几点原因:

最现实的原因就是为了找工作,数据库是岗位的需求,所以要学。

其次就是现在是大数据时代,数据是非常重要的,得数据者得天下。

然后就是我们需要存储数据,这就要用到数据库了。

最后就是数据库是所有软件体系中最核心的存在

什么是数据库?

数据库即DataBase(DB),它是存放数据的仓库,它的存储空间很大,可以存放百万条、千万条、上亿条数据。

数据库是一个按照数据结构来存储和管理数据的计算机软件系统,安装在操作系统之上。

数据库的作用说白了就是:存储数据、管理数据。

数据库的分类

数据库可以分为关系型数据库和非关系型数据库。

关系型数据库:(SQL)

关系型数据库,存储的格式可以直接且直观地反映实体间的关系。关系型数据库中表与表之间是有很多复杂的关联关系的。

常见的关系型数据库有MySQL,SqlServer,Oracle,DB2,SQLlite等。

在轻量或小型应用中,使用不同的关系型数据库对系统的性能影响不大,但是在构建大型应用时,需要根据应用的业务需求和性能需求,选择合适的关系型数据库。

关系型数据库大多都遵循SQL(Structured Query Language,结构化查询语言)标准,常见操作有查询(SELECT)、新增(INSERT)、更新(UPDATE)、删除(DELETE)等。

关系型数据库通过表和表之间、行和列之间的关系进行数据的存储。

非关系型数据库(NoSQL)

非关系型数据库指的是分布式的、非关系型的、不保证遵循ACID原则的数据存储系统。

NoSQL数据库有MongoDB,Redis,Memcache等。

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

非关系型数据库的设计目的是简化数据库结构、避免冗余、影响性能的表连接、摒弃复杂分布式。

NoSQL数据库适合追求速度和可扩展性、业务多变的应用场景。

数据库管理系统简称DBMS,它是数据库的管理软件,可以科学有效地管理、维护和获取数据。MySQL就是数据库管理系统。

MySQL

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,现属于Oracle公司。MySQL是最流行的关系型数据库管理系统之一,在web应用方面,MySQL是最好的RDBMS(Relational Database Management System,关系数据库管理系统)应用软件之一。

数据库的操作

对数据库的操作实际上是对数据库中表中的数据的操作。

数据库的基本操作

创建数据库

CREATE DATABASE IF NOT EXISTS school;

删除数据库

DROP DATABASE IF EXISTS school;

使用数据库

USE school;

查看数据库

SHOW DATABASES;

如果表名或者字段名是一个特殊的字符,那么就要使用tab键上的那个符号(``)将其括起来。如

CREATE DATABASE `school`;

数据库的列类型

常用的数据库的列类型。

数值

类型含义字节数
tinyint十分小的数据1个字节
smallint较小的数据2个字节
mediumint中等大小的数据3个字节
int标准的整数4个字节(常用)
bigint较大的数据8个字节
float浮点数4个字节
double浮点数8个字节(存在精度问题)
decimal字符串形式的浮点数16个字节(不存在精度损失,常用语金融计算)

字符串

类型含义大小
char字符串固定大小的0~255
varchar可变字符串0~65535(常用)
tinytext微型文本2^8-1
text文本串2^16-1(保存大文本)

时间日期

类型格式
dateYYYY-MM-DD,日期格式
timeHH:mm:ss,时间格式
datetimeYYYY-MM-DD HH:mm:ss ,最常用的时间格式
timestamp时间戳,从1970.1.1到现在的毫秒数。常用
year表示年份

null

null表示没有值,未知的。

不要使用null进行运算,因为结果为null

数据库的字段属性

字段属性含义
Unsigned表示无符号的整数。表明该列不能声明为负数
Zerofill0填充。不足的位数,使用0来填充
自增自增,即自动在上一条记录的基础上加1(默认)。通常用来设计唯一的主键,必须是整数类型。可以自定义设计主键自增的起始值和步长。
非空(NULL/NOT NULL)j假设设置为not null,如果不赋值,就会报错。假设设置为null,如果不填写值,默认就为null。
默认设置默认的值。例如设置sex字段默认值为男,如果不指定该列的值,那么就会有默认的值。

每一个表都必须存在以下五个字段。这是用于做项目的,表示一个记录存在意义!

字段含义
id主键
version乐观锁
is_delete伪删除
gmt_create创建时间
gmt_update修改时间

创建数据库表

创建数据库表的格式:

CREATE TABLE [IF NOT EXISTS] `表名` (
	`字段名` 列类型 [属性] [索引] [注释],
    `字段名` 列类型 [属性] [索引] [注释],
    ......
    `字段名` 列类型 [属性] [索引] [注释]
)[表类型][字符集设置][注释]

在school数据库中创建一个student表。

CREATE TABLE IF NOT EXISTS `student`(
  `id` INT(4) NOT NULL AUTO_INCREMENT COMMENT '学号',
  `name` VARCHAR(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
  `pwd` VARCHAR(20) NOT NULL DEFAULT '123456' COMMENT '密码',
  `sex` VARCHAR(2) NOT NULL DEFAULT '女' COMMENT '性别',
  `birthday` DATETIME DEFAULT NULL COMMENT '出生日期',
  `address` VARCHAR(100) DEFAULT NULL COMMENT '家庭住址',
  `email` VARCHAR(50) DEFAULT NULL COMMENT '邮箱',
  PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8

几个常用命令:

查看创建数据库的语句

SHOW CREATE DATABASE school

查看创建表的定义语句

SHOW CREATE TABLE student

显示表的结构

DESC student
-- mysql的注释为--,且需要在--和注释内容之间空一格

数据库表的类型

在创建数据库和表的时候会定义引擎,常用的有两种:INNODB(默认使用)和MYSIAM(早些年使用)。

两者的区别主要有以下:

MYISAMINNODB
事务支持不支持支持
数据行锁定不支持支持
外键约束不支持支持
全文索引支持不支持
表空间的大小较小较大,约为2倍

常规的使用操作:

  • MYISAM:节约空间,速度较快
  • INNODB:安全性高,事务的处理,多表多用户操作

在物理空间存在的位置

所有的数据库文件都存在data目录下,一个文件夹就对应一个数据库。本质还是文件的存储。

MySQL引擎在物理文件上的区别:

  • INNODB:在数据库表中只有一个 *.frm文件,以及上级目录下的ibdata1文件。

  • MYISAM对应文件

    • *.frm文件:表结构的定义文件
    • *.MYD文件:数据文件(data)
    • *.MYI文件:索引文件(index)

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

CHARSET=utf8

不设置字符集编码的话,会使用MySQL默认的编码 Latin1,该编码不支持中文。

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

character-set-server=utf8

表的修改和删除

表的修改

修改表名 ALTER TABLE 旧表名 RENAME AS 新表名;

ALTER TABLE student RENAME AS student01;

增加表的字段 ALTER TABLE 表名 ADD 字段 列属性;

ALTER TABLE student01 ADD grade INT(3);

修改表的字段–修改约束 ALTER TABLE 表名 MODIFY 字段 列属性[]

ALTER TABLE student01 MODIFY grade VARCHAR(11) -- 修改约束

修改表的字段–字段重命名 ALTER TABLE 表名 CHANGE 旧名字 新名字 列属性[]

ALTER TABLE student01 CHANGE grade grade1 INT(2) 

删除表的字段 ALTER TABLE 表名 DROP 字段名

ALTER TABLE student01 DROP grade1

表的删除

-- 删除表(考虑表如果存在再去删除)
DROP TABLE IF EXISTS student01

在进行表的创建和删除操作时,应该加上判断避免报错

MySQL数据管理

外键

外键:表的外键是另一表的主键,外键可以有重复的,可以是空值。外键表示了两个关系之间的相关联系。

外键有两种创建方式。

方式一

在创建表的时候,就增加约束来创建外键。但这样做的缺点是麻烦且复杂。

CREATE TABLE `grade`(
  `gradeid` INT(10) NOT NULL AUTO_INCREMENT COMMENT '年级id',
  `gradename` VARCHAR(50) NOT NULL COMMENT '年级名称',
  PRIMARY KEY (`gradeid`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
-- 学生表的 gradeid 字段 要去引用年级表的 gradeid
-- 定义外键key
-- 给这个外键添加约束 (执行引用) references 引用
CREATE TABLE IF NOT EXISTS `student` (
  `id` INT(4) NOT NULL AUTO_INCREMENT COMMENT '学号',
  `name` VARCHAR(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
  `pwd` VARCHAR(20)NOT NULL DEFAULT '123456' COMMENT '密码',
  `sex` VARCHAR(2) NOT NULL DEFAULT '女' COMMENT '性别',
  `birthday` DATETIME DEFAULT NULL COMMENT '出生日期',
  `gradeid` INT(10) NOT NULL COMMENT '学生的年级',
    `address` VARCHAR(100) DEFAULT NULL COMMENT '家庭住址',
  `email` VARCHAR(50) DEFAULT NULL COMMENT '邮箱',
  PRIMARY KEY(`id`),
  KEY `FK_gradeid` (`gradeid`),
  CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES
`grade`(`gradeid`)
)ENGINE=INNODB DEFAULT CHARSET=utf8

删除有外键关系的表的时候,必须先要删除引用别人的表(从表),然后再删除被引用的表(主表)。

方式二

创建表成功后,添加外键约束。

CREATE TABLE `grade`(
  `gradeid` INT(10) NOT NULL AUTO_INCREMENT COMMENT '年级id',
  `gradename` VARCHAR(50) NOT NULL COMMENT '年级名称',
  PRIMARY KEY (`gradeid`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
-- 学生表的 gradeid 字段 要去引用年级表的 gradeid
-- 定义外键key
-- 给这个外键添加约束 (执行引用) references 引用
CREATE TABLE IF NOT EXISTS `student` (
  `id` INT(4) NOT NULL AUTO_INCREMENT COMMENT '学号',
  `name` VARCHAR(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
  `pwd` VARCHAR(20)NOT NULL DEFAULT '123456' COMMENT '密码',
  `sex` VARCHAR(2) NOT NULL DEFAULT '女' COMMENT '性别',
  `birthday` DATETIME DEFAULT NULL COMMENT '出生日期',
  `gradeid` INT(10) NOT NULL COMMENT '学生的年级',
  `address` VARCHAR(100) DEFAULT NULL COMMENT '家庭住址',
  `email` VARCHAR(50) DEFAULT NULL COMMENT '邮箱',
  PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
-- 创建表的时候没有外键关系
ALTER TABLE `student`
ADD CONSTRAINT `FK_gradeid` FOREIGN KEY(`gradeid`) REFERENCES
`grade`(`gradeid`);
ALTER TABLE 表名 ADD CONSTRAINT 约束名 FOREIGN KEY(作为外键的列) REFERENCES 哪个表(哪个字段)

上面的操作都是物理外键,是数据库级别的外键,不建议使用(避免数据库过多造成困扰)。

最佳的实现就是

  • 数据库就是单纯的表,只用来存数据,只有行(数据)和列(字段)
  • 若想使用多张表的数据,想使用外键则通过程序来实现

DML语言

DML:Data Manipulation Language,数据库操作语言。通过该语言可以实现对数据库的基本操作。

DML基本的操作是:

  • 插入
  • 修改
  • 删除

插入(添加)操作

插入操作使用 INSERT。

插入的语法为:INSERT INTO 表名([字段名1,字段名2,字段名3]) VALUES ('值1'),('值2'),('值3',...)

-- INSERT INTO 表名([字段名1,字段名2,字段名3]) VALUES ('值1'),('值2'),('值3',...)
INSERT INTO `grade`(`gradename`) VALUES ('大一') -- 由于主键是自增的,我们可以省略
-- 如果不写表的字段,就会一一匹配
INSERT INTO `grade` VALUES('大三')

一般写插入语句时,一定要数据和字段一一对应

INSERT INTO `student`(`name`,`pwd`,`sex`) VALUES ('张三','123456','男')
-- 插入多个字段
INSERT INTO `grade`(`gradename`)
VALUES('大二'),('大四')

需要注意的是:

  • 字段和字段之间使用英文逗号隔开
  • 字段可以省略,但是后面的值还是要一一对应
  • 可以同时插入多条数据,VALUES后面的值使用英文逗号隔开即可

修改操作

修改使用 UPDATE

修改操作的语法为:update 表名 set column_name=value,[column_name=value,...] where [条件]

-- 修改名字,带了条件
UPDATE `student` SET `name`='李四' WHERE id = 1;
-- 在不指定条件的情况下,会改动所有表!
UPDATE `student` SET `name`='王五'
-- 修改多个属性,使用逗号隔开
UPDATE `student` SET `name`='张三',`age`='23' WHERE id = 1;

where id = 1 是一个条件句。where + 判断条件(字段 操作符 某个值/区间)

where操作符会返回一个布尔值。

操作符含义示例结果
=等于5=6false
<> 或者 !=不等于5<>6/5!=6true
>大于10>8true
<小于10<8false
>=大于等于8>=8true
<=小于等于16<=20true
between … and …在某个范围内5 between 1 and 10true
and且/和5>2 and 2>3false
or5>2 or 2>3true

对于修改的语法。需要注意的有:

  • column_name 是数据库的列,所以最好带上``
  • 修改的时候如果没有带筛选的条件,则会修改所有的列
  • value 是一个具体的值,也可以是一个变量
  • 多个设置的属性之间,使用英文逗号隔开

删除操作

删除使用 delete。

删除的语法:delete from 表名 [where 条件]

-- 删除指定数据
DELETE FROM `student` WHERE id = 1;
-- 删除时如果没有带条件,则会全部删除,所以尽量避免这样写
DELETE FROM `student`;

TRUNCATE 命令

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

-- 清空 student 表
TRUNCATE `student`

delete和truncate的区别

  • 相同点:两者都可以删除数据库表,都不会删除表结构
  • 不同点
    • truncate 会重新设置自增列,计数器会归零
    • truncate不会影响事务

delete删除的问题:重启数据库后的现象

  • INNODB:自增列会从1开始(存在内存中,断电即失)
  • MYISAM:继续从上一个自增量开始(存在文件中,不会丢失)

DQL查询数据

DQL

DQL:Data Query LANGUAGE,数据查询语言。

对于DQL而言,所有的查询操作都使用它(select);简单查询、复杂查询都可以做到;它是数据库中最核心的语言,也是最重要的语句;它是使用频率最高的语句。

select 语法

SELECT [ALL | DISTINCT]
{* | table.* | [table.field[as alias1][,table.field2[as alias2]][,...]] }
FROM table_name [as table_alias]
	[left | right |inner join table_name2]  -- 联合查询
	[WHERE ...]      -- 指定结果需满足的条件
	[GROUP BY ...]   -- 指定结果按照哪几个字段来分组
	[HAVING ...]     -- 过滤分组的记录必须满足的次要条件
	[ORDER BY ...]   -- 指定查询记录按一个或多个条件排序
	[LIMIT {[offset,]row_count | row_countOFFSET oeeset}];        -- 指定查询的记录从哪条至哪条

注意:[ ]括号表示可选的,{ }括号表示必选的

查询字段

语法:select 字段 from 表名

-- 查询全部的学生    select 字段 from 表名
SELECT * FROM `student`
-- 查询指定的字段
SELECT `StudentNo`,`StudentName` from student

有时候,列名字不是很见名知意,可以起别名,使用as。

字段名 as 别名;表名 as 别名

-- 起别名 AS   给结果起一个名字  可以给字段、表起别名
SELECT `StudentNo` AS 学号,`StudentName` AS 学生姓名 from student
-- 拼接函数 concat(a,b)
SELECT CONCAT('姓名:',StudentName) AS 新名字 FROM student

distinct 去重

distinct的作用是:去除select查询出来的结果中重复的数据,即重复的数据只显示一条即可。

-- 发现重复数据,去重
SELECT DISTINCT `StudentNo` FROM result 

数据库的列

-- 查询系统版本(select+函数)
SELECT VERSION()
-- 可以用来计算(select+表达式)
SELECT 20-8 AS 计算结果
-- 查询自增的步长(select+变量)
SELECT @@auto_increment_increment
-- 考试成绩 + 1分查看
SELECT `StudentNo`,`StudentResult`+1 AS '提分后' FROM result

数据库中的表达式可以是:文本值,列,null,函数,计算表达式,系统变量等

语法:select 表达式 from 表

where条件子句

where条件字句的作用是于检索数据库中符合条件的值。搜索的条件由一个或者多个表达式组成。结果是布尔值。

where中用到的逻辑运算符

运算符语法描述
and &&a and b / a && b逻辑与,两个都为真,则结果为真
or ||a or b / a ||b逻辑或,其中一个为真,则结果为真
not !not a / ! a逻辑非,真为假,假为真
-- and 
SELECT StudentNo,`StudentResult` FROM result
WHERE StudentResult>=80 AND StudentResult<=100
-- &&
SELECT StudentNo,`StudentResult` FROM result
WHERE StudentResult>=80 && StudentResult<=100
-- !
SELECT studentNo,`StudentResult` FROM result
WHERE studentNo!=1000;
-- not
SELECT studentNo,`StudentResult` FROM result
WHERE NOT studentNo = 1000

模糊查询 比较运算符

运算符语法描述
is nulla is null如果a为null,结果为真
is not nulla is not null如果a不为null,结果为真
betweena between b and cf如果a在b和c之间,则结果为真
likea like bsql匹配,如果a匹配b,则结果真
ina in (a1,a2,a3,…)r如果a在a1,a2,a3,…中的其中的某一个值中,则结果为真
-- like 结合 %(代表0到任意个字符)    _(代表一个字符)
-- 查询所有姓刘的学生
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
SELECT `StudentNo`,`StudentName` FROM `student`
WHERE StudentNo IN (1,3,5,6);
-- null   not null
-- not null
SELECT `StudentNo`,`StudentName` FROM `student`
WHERE `BornDate` IS NOT NULL
-- null
SELECT `StudentNo`,`StudentName` FROM `student`
WHERE `BornDate` IS NULL

联表查询

联表查询使用 join。联表查询有三大类。

查询方式描述
inner join如果表中至少有一个匹配,就返回行
left join会从左表中返回所有的值,即使右表中没有匹配
right join会从右表中返回所有的值,即使左表中没有匹配

join的语法:join(连接的表) on(判断的条件)

-- inner join
SELECT s.studentNO,studentName,SubjectNo,StudentResult
FROM student AS s
INNER JOIN result AS r
ON s.studentNO = r.studentNO

-- left join 
SELECT s.studentNO,studentName,SubjectNo,StudentResult
FROM student s
LEFT JOIN result r
ON s.studentNO = r.studentNO

-- right join
SELECT s.studentNO,studentName,SubjectNo,StudentResult
FROM student s
RIGHT JOIN result r
ON s.studentNO = r.studentNO

联表查询的思路是:

  1. 分析需求,分析查询的字段分别来自哪些表
  2. 确定使用哪种连接查询
  3. 确定交叉点(即两、三张表中哪个数据是相同的)

对于多表查询:

首先,要查询哪些数据。select …

其次,要从哪几张表中查。from 表 xxx join 连接的表 on 交叉条件

多张表查询时,先查询两张表然后再慢慢增加。

join是连接查询,where是等值查询

自连接

自连接是自己的表和自己的表进行连接,核心是将一张表拆为两张一样的表。

分页和排序

排序

排序的方式有两种,升序(ASC)和降序(DESC)。

排序的语法:order by 哪个字段 排序方式

SELECT s.`StudentNo`,`StudentName`,`SubjectName`,`StudentResult`
FROM student s
INNER JOIN `result` r
ON s.StudentNo = r.StudentNo
INNER JOIN `subject` sub
ON r.`SubjectNo` = sub.`SubjectNo`
WHERE subjectName = '数据库结构-1'
ORDER BY StudentResult ASC

分页

分页的目的是 为了缓解数据库的压力,使用户的体验感更好。网页中就应用了分页。

分页的语法:limit 起始值,页面的大小

SELECT s.`StudentNo`,`StudentName`,`SubjectName`,`StudentResult`
FROM student s
INNER JOIN `result` r
ON s.StudentNo = r.StudentNo
INNER JOIN `subject` sub
ON r.`SubjectNo` = sub.`SubjectNo`
WHERE subjectName = '数据库结构-1'
ORDER BY StudentResult ASC
LIMIT 5,5

分页的一些计算

每页只显示五条数据
第一页 limit 0,5    (1-1)*5
第二页 limit 5,5    (2-1)*5
第三页 limit 10,5   (3-1)*5
第N页 limit(n-1)* pageSize,pageSize
【pageSize:页面大小】
【(n-1)* pageSize:起始值】
【n :当前页 】
【数据总数/页面大小 = 总页数】

子查询

当一个查询时另一个查询的条件时,称之为子查询。

本质就是 在where语句中嵌套一个子查询语句

SELECT StudentNo,StudentName FROM student WHERE StudentNo IN (
SELECT StudentNo FROM result WHERE StudentResult>80 AND SubjectNo = (
SELECT SubjectNo FROM `subject` WHERE `SubjectName` = '高等数学-2')
)

分组和过滤

分组是通过某个字段来进行分组。

过滤则是根据某个条件或某些条件来进行筛选。

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

MySQL函数

常用函数

数学运算

-- 绝对值
SELECT ABS(-5) 
-- 向上取整
SELECT CEILING(5.4) 
-- 向下取整
SELECT FLOOR(5.4) 
-- 返回一个 0~1 之间的随机数
SELECT RAND() 
-- 判断一个数的符号 0返回0 负数返回-1,正数返回 1
SELECT SIGN(10) 

字符串函数

-- 字符串长度
SELECT CHAR_LENGTH('hello,world') 
-- 拼接字符串
SELECT CONCAT('我','爱','你') 
-- 查询,从某个位置开始替换某个长度
SELECT INSERT('我爱编程helloworld',1,2,'超级热爱') 
-- 小写字母
SELECT LOWER('Hello') 
-- 大写字母
SELECT UPPER('Hello') 
-- 返回第一次出现的子串的索引
SELECT INSTR('Hello','l') 
-- 替换出现的指定字符串
SELECT REPLACE('我爱编程','爱','超级热爱') 
-- 返回指定的子字符串 (源字符串,截取的位置,截取的长度)
SELECT SUBSTR('我爱编程helloworld',4,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()

想要查询一个表中有多少个记录,可以使用count()。

count(字段)会忽略所有的null值
count(*)不会忽略null值。本质是计算行数
count(1)不会忽略null值。本质是计算行数

如果表没有主键,那么count(1)比count( * )快。表有主键,count(*)会自动优化到主键列上。

数据库级别的MD5加密

MD5

MD5:Message-Digest Algorithm,是一种被广泛使用的密码散列函数。主要增强算法复杂度和不可逆性。

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

UPDATE testmd5 SET pwd=MD5(pwd) WHERE id = 1

使用MD5,校验的时候,需要将用户传递进来的值进行MD5加密,然后在数据库中对比加密后的值。

事务

事务:Transaction,一般是指要做的或所做的事情。

在mysql中,事务是将一组SQL放在一个批次中去执行。

事务的原则是:ACID原则

A:原子性(Atomicity)

原子性即 事务要么都成功,要么都失败,不存在一方成功一方失败的情况(会出错)。

B:一致性(Consistency)

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

I:隔离性(Isolation)

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

D:持久性(Durability)

持久性是针对事务提交的,事务一旦提交则不可逆,将被持久化到数据库中。

隔离导致的一些问题


脏读

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

不可重复读

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

虚读(幻读)

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

执行事务

-- mysql 是默认开启事务自动提交的
SET autocommit = 0 /* 关闭 */
SET autocommit = 1 /* 开启(默认的) */

-- 手动处理事务
SET autocommit = 0 -- 关闭自动提交
-- 事务开启
START TRANSACTION -- 标记一个事务的开始,从这个之后的 sql 都在同一个事务内
INSERT xx
INSERT xx
-- 提交: 持久化 (成功!)
COMMIT
-- 回滚: 回到的原来的样子 (失败!)
ROLLBACK
-- 事务结束
SET autocommit = 1 -- 开启自动提交

索引

MySQL官方对索引的定义是:索引(Index)是帮助MySQL高效获取数据的数据结构

InnoDB 的默认数据结构是 BTree

索引分类

索引可以分为:

  • 主键索引(PRIMARY KEY)
    • 这是唯一的标识。主键是不可重复的,只能有一个列作为主键。
  • 唯一索引(UNIQUE KEY)
    • 可以避免重复的列出现。唯一索引是可以重复的,多个列都可以标识为 唯一索引。
  • 常规索引(KEY/INDEX)
    • 常规索引是默认的,使用index,key关键字来设置。
  • 全文索引(FullText)
    • 在特定的数据库引擎下才有,如MyISAM。
    • 可以快速定位数据。

基本语法

索引的创建:

  • 在创建表的时候给字段增加索引
  • 创建成功表后,增加索引
-- 显示所有的索引信息
SHOW INDEX FROM student
-- 增加一个全文索引 (索引名) 列名
ALTER TABLE school.student ADD FULLTEXT INDEX `studentName`(`studentName`);

索引在小数据量的时候,用处不大,但是在大数据的时候,区别十分明显~

索引的原则

  • 索引不是越多越好
  • 不要对进程变动数据加索引
  • 小数据量的表不需要加索引
  • 索引一般加在常用来查询的字段上

权限管理和备份

用户管理

方式一

使用可视化管理工具进行用户的管理。

方式二

使用SQL命令进行用户的管理,实际上操作的是 mysql.user这张表。本质也是对表的增删改查。

-- 创建用户 CREATE USER 用户名 IDENTIFIED BY '密码'
CREATE USER zhangsan IDENTIFIED BY '123456'
-- 修改密码
-- 修改当前用户密码
SET PASSWORD = PASSWORD('123456')

-- 修改指定用户密码
SET PASSWORD FOR zhangsan = PASSWORD('1234567')
-- 重命名 RENAME USER 原来名字 TO 新的名字
RENAME USER zhangsan TO zhangsan02
-- 用户授权 ALL PRIVILEGES 全部的权限 (可以对数据库和表)
-- ALL PRIVILEGES 除了给别人授权,其他都能够干
GRANT ALL PRIVILEGES ON *.* TO zhangsan02
-- 查询权限
-- 查看指定用户的权限
SHOW GRANTS FOR zhangsan02 
SHOW GRANTS FOR root@localhost
-- 撤销权限 REVOKE 哪些权限, 在哪个库撤销,给谁撤销
REVOKE ALL PRIVILEGES ON *.* FROM zhangsan02
-- 删除用户
DROP USER zhangsan02

备份

备份的原因:

  • 保证数据不丢失
  • 数据转移

MySQL数据库备份的方式:

  • 直接拷贝物理文件

  • 在可视化工具中手动导出

    • 在想要导出的表或库中,右键选择备份或导出
  • 使用命令行导出(mysqldump命令)

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

数据的导入:

# 导入
# 登录的情况下,切换到指定的数据库
# source 备份文件
source d:/a.sql
mysql -u用户名 -p密码 库名< 备份文件

规范数据库设计

当数据比较复杂的时候,就需要设计数据库。

数据库的设计也有好坏之分。

糟糕的数据库设计会产生一系列问题:

  • 数据冗余,浪费空间
  • 数据库插入和删除都很麻烦,且产生异常
  • 程序性能差

良好的数据库设计的优点是:

  • 节省内存空间
  • 保证数据库的完整性
  • 方便开发系统

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

当数据库不规范时,会产生一系列问题:

  • 信息重复
  • 更新异常
  • 插入异常:无法正常显示信息
  • 删除异常:丢失有效的信息

在软件开发中,设计数据库时涉及到两方面:分析需求(分析业务和需要处理的数据库的需求)和概要设计(设计关系图 E-R图)。

设计数据库的步骤:

  • 收集信息,分析需求
  • 标识实体:把需求落地到每个字段
  • 标识实体之间的关系

三大范式

第一范式(1NF)

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

第二范式(2NF)

前提是要满足第一范式。每张表只描述一件事情。

第三范式(3NF)

前提是要满足第一范式和第二范式。

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

在进行规范数据库的设计时,会产生 规范性和性能的问题。针对这样的问题,需要考虑以下:

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

  • 考虑商业化的需求和目标,数据库的性能更加重要。
  • 在规范性能的问题的时候,需要适当考虑一下规范性。
  • 故意给某些表增加一些冗余的字段。从多表查询中变为单表查询。
  • 故意增加一些计算列。从大数据量降低为小数据量的查询。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值