人类在进化的过程中,创造了数字、文字、符号等来进行数据的记录,往石头和龟壳上面画上,到时候一数,但是承受着认知能力和创造能力的提升,数据量越来越大,对于数据的记录和准确查找,成为了一个重大难题

数据库的前世今生

数据库是什么?

首先我们先来聊聊数据库,首先数据库是什么意思,其实就是数据的仓库,而数据才是最关键的,现在大家所说的大数据大数据,其实说白了数据才是核心,通过各种算法要分析数据。

为什么我们需要数据库?

其实在一些传统的大企业来说,有的在使用纸质文件(那就要注意防火、防潮),有的在使用excel来存储数据,这个是真实存在的,上一家单位就是这样,公司人员excel的各种公式很66 的,但是也面临着改革

公司里面都开始提倡无纸化办公,让打印出来纸质的资料越来越少,连公司前台的签到都变成了二维码,而excel里面的大量的数据累积,让我们查找和维护变的异常困难,存储这些文件的服务器变的重要多了,万一中了个病毒倒了下去,这些数据再也没有办法恢复过来

数据库解决的问题

持久化存储,优化读写(并不是简单的IO读写,每个数据库这个才是核心,算法不同),保证数据的有效性(比如有效的身份证号,以前手工录入很容易出现重复的)

常用的数据库种类都有什么

  1. 关系型数据库(Oracle/MySQL/SQL SERVER/ACCESS..)
  2. 非关系型数据库(MongoDB/Redis/Memcached..)

学习前的名词解释

图片描述

MySQL的介绍

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle公司(被Oracle收购)MySQL目前用的比较多,毕竟一个标签就是免费嘛,一些创业公司首选了http://www.mysql.com/ mysql官网
https://db-engines.com/en/ran... 数据库排名网站

MySQL是一种关联数据库管理系统,关联数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性

MySQL的特点:

  1. Mysql是开源的,所以你不需要支付额外的费用
  2. Mysql支持大型的数据库。可以处理拥有上千万条记录的大型数据库
  3. MySQL使用标准的SQL数据语言形式
  4. Mysql可以允许于多个系统上,并且支持多种语言。这些编程语言包括C、C++、Python、Java、Perl、PHP、Eiffel、Ruby和Tcl等。
  5. Mysql对PHP有很好的支持,PHP是目前最流行的Web开发语言。
  6. MySQL支持大型数据库,支持5000万条记录的数据仓库,32位系统表文件最大可支持4GB,64位系统支持最大的表文件为8TB。
  7. Mysql是可以定制的,采用了GPL协议,你可以修改源码来开发自己的Mysql系统。

上次去听京东的技术峰会,京东的数据库就是基于Mysql进行了定制化开发

MySQL的安装图解

数据库设计

E-R模型
ER模型最早由Peter Chen(陈品山)于1976年提出,当前物理的数据库都是按照E-R模型进行设计的(E表示entry,实体,R表示relationship,关系)一个实体转换为数据库中的一个表,关系描述两个实体之间的对应规则,包括(一对一,一对多,多对多)

通俗点理解下关系:
一对一:一个部门有一个经理,而每个经理只在一个部门任职,则部门与经理的联系是一对一的
一对多:一个员工可以同时是多个部门的经理,而一个部门只能有一个经理,则这种规定下“员工”与“部门”之间的“管理”联系就是1:n的联系了
多对多:一个员工可以同时在多个部门工作,而一个部门有多个员工在其中工作,则“员工”与“部门”的“工作”联系为m:n联系

数据库设计阶段,我们会通过工具(Visio/PowerDesigner..)绘制E-R图,E-R图也称实体-联系图(Entity Relationship Diagram),提供了表示实体类型、属性和联系的方法,用来描述现实世界的概念模型
图片描述

数据库设计规范:三范式
第一范式(1NF):列不可拆分,比如姓名已经不可以再拆,但是这个要根据具体的业务逻辑走,你可以再拆,姓一个字段,名一个字段
第二范式(2NF):唯一标识,可以通过一个属性唯一的找到这个对象,如果没有这个标识很容易造成数据重复,冗余 (注意:数据库设置的时候范式都要满足)
第三范式(3NF):引用主键,这个是基于第二范式来说的,一个表想引用另外一个表的数据,那么需要主键来引用,需要唯一标识

上面这些规范不仅仅是作用mysql数据库,只要是关系型数据库都应该遵守上面的规范

mysql中常用的字段类型

数字:int (整数) decimal(5,2) 保留2位小数,5是整数部分加小数部分的总长度
字符串:char,varchar,text(大文本)
char与varchar后面接的数据大小为存储的字符数
char是固定长度,如果字符数没有达到定义位数会在后面自动补空格 例:char(5) 'abc '
varchar是变长长度,例:varchar(5) 'abc' 不会帮你补空格
日期:datetime
布尔:bit

约束

  1. 主键primary key
  2. 非空not null
  3. 唯一 unique
  4. 默认default
  5. 外键foreign key

SQL语言

先来说说什么是SQL?

SQL(SQL 是一种 ANSI 的标准计算机语言 【ANSI,美国国家标准化组织】) 是用于访问和处理数据库的标准的计算机语言,使我们有能力访问数据库(Oracle, Sybase, SQL Server, DB2, Access 等等)

SQL能做什么? 帮你操作数据库,比如执行查询、删除、修改、添加、创建表、存储过程、视图等等等你想要对数据库做的操作都可以

那是不是学会SQL 就可以对上面那群数据库操作了,只能说大部分是的,但是个别情况会有点区别,因为SQL语言的版本问题。

查询操作

查询的基本语法:

select * from 表名;

解读下上面这条语句:

  1. from关键字后面写表名,表示数据来源于是这张表
  2. select后面写表中的列名,如果是*表示在结果中显示表中所有列
  3. 在select后面的列名部分,可以使用as为列起别名,这个别名出现在结果集中
  4. 如果要查询多个列,之间使用逗号分隔

消除重复行

在select后面列前使用distinct可以消除重复的行

select distinct gender from students;

根据条件查询

语法如下:

select * from 表名 where 条件;

使用where子句对表中的数据筛选,结果为true的行会出现在结果集中
比较运算符包括 = > < >= <= !=或<>

比较运算符的栗子:

/*查询编号大于3的学生*/
select * from students where id>3;
/*查询编号不大于4的科目*/
select * from subjects where id<=4;
/*查询姓名不是“黄蓉”的学生*/
select * from students where sname!='黄蓉';
/*查询没被删除的学生*/
select * from students where isdelete=0;

逻辑运算符包括 and or not

逻辑运算符的栗子:

/*查询编号大于3的女同学*/
select * from students where id>3 and gender=0;
/*查询编号小于4或没被删除的学生*/
select * from students where id<4 or isdelete=0;

模糊查询

  1. like
  2. %表示任意多个任意字符
  3. _表示一个任意字符
/*查询姓黄的学生*/
select * from students where sname like '黄%';
/*查询姓黄并且名字是一个字的学生*/
select * from students where sname like '黄_';
/*查询姓黄或叫靖的学生*/
select * from students where sname like '黄%' or sname like '%靖%';

范围查询

  1. in表示在一个非连续的范围内
  2. between ... and ...表示在一个连续的范围内
/*查询编号是1或3或8的学生*/
select * from students where id in(1,3,8);
/*查询学生是3至8的学生*/
select * from students where id between 3 and 8;
/*查询学生是3至8的男生*/
select * from students where id between 3 and 8 and gender=1;

空判断
注意:null与''是不同的,判空is null 判非空is not null

/*查询没有填写地址的学生*/
select * from students where hometown is null;
/*查询填写了地址的学生*/
select * from students where hometown is not null;
/*查询填写了地址的女生*/
select * from students where hometown is not null and gender=0;

优先级

  1. 小括号,not,比较运算符,逻辑运算符
  2. and比or先运算,如果同时出现并希望先算or,需要结合()使用

聚合

为了快速得到统计数据,提供了5个聚合函数:

  1. count(*)表示计算总行数,括号中写星与列名,结果是相同的
  2. max(列)表示求此列的最大值
  3. min(列)表示求此列的最小值
  4. sum(列)表示求此列的和
  5. avg(列)表示求此列的平均值

栗子:

/*查询学生总数*/
select count(*) from students;
/*查询女生的编号最大值*/
select max(id) from students where gender=0;
/*查询未删除的学生最小编号*/
select min(id) from students where isdelete=0;
/*查询男生的编号之后*/
select sum(id) from students where gender=1;
/*查询未删除女生的编号平均值*/
select avg(id) from students where isdelete=0 and gender=0;

分组
按照字段分组,表示此字段相同的数据会被放到一个组中,分组后,只能查询出相同的数据列,对于有差异的数据列无法出现在结果集中,可以对分组后的数据进行统计,做聚合运算

语法:

select 列1,列2,聚合... from 表名 group by 列1,列2,列3...

栗子:

/*查询男女生总数*/
select gender as 性别,count(*)
from students
group by gender;
/*查询各城市人数*/
select hometown as 家乡,count(*)
from students
group by hometown;

分组后的数据筛选

语法:

select 列1,列2,聚合... from 表名
group by 列1,列2,列3...
having 列1,...聚合...

having后面的条件运算符与where的相同

/*查询男生总人数*/
方案一
select count(*)
from students
where gender=1;
-----------------------------------
方案二:
select gender as 性别,count(*)
from students
group by gender
having gender=1;

对比where与having

  1. where是对from后面指定的表进行数据筛选,属于对原始数据的筛选
  2. having是对group by的结果进行筛选

排序

为了方便查看数据,可以对数据进行排序,语法:

select * from 表名
order by 列1 asc|desc,列2 asc|desc,...

注意:

  1. 将行数据按照列1进行排序,如果某些行列1的值相同时,则按照列2排序,以此类推
  2. 默认按照列值从小到大排列
  3. asc从小到大排列,即升序
  4. desc从大到小排序,即降序

栗子:

/*查询未删除男生学生信息,按学号降序*/
select * from students
where gender=1 and isdelete=0
order by id desc;
/*查询未删除科目信息,按名称升序*/
select * from subject
where isdelete=0
order by stitle;

获取部分行
当数据量过大时,在一页中查看数据是一件非常麻烦的事情。
语法:

select * from 表名
limit start,count

从start开始,获取count条数据,start索引从0开始
示例:分页
已知:每页显示m条数据,当前显示第n页
求总页数:此段逻辑后面会在python中实现
查询总条数p1
使用p1除以m得到p2
如果整除则p2为总数页
如果不整除则p2+1为总页数
求第n页的数据

/*语法*/
select * from students
where isdelete=0
limit (n-1)*m,m

栗子
查询第1条到第10条的数据的sql是:select from table limit 0,10; ->对应我们的需求就是查询第一页的数据:select from table limit (1-1)*10,10;

查询第10条到第20条的数据的sql是:select from table limit 10,20; ->对应我们的需求就是查询第二页的数据:select from table limit (2-1)*10,10;

高级查询

关系
图片描述
我们去设计数据库的时候会存在表与表之间的依赖关系,那么查询的时候就会设计到依赖关系的连接查询
连接查询

连接查询分类如下:

  1. 表A inner join 表B:表A与表B匹配的行会出现在结果中
  2. 表A left join 表B:表A与表B匹配的行会出现在结果中,外加表A中独有的数据,未对应的数据使用null填充
  3. 表A right join 表B:表A与表B匹配的行会出现在结果中,外加表B中独有的数据,未对应的数据使用null填充

注意:在查询或条件中推荐使用“表名.列名”的语法,如果多个表中列名不重复可以省略“表名.”部分,如果表的名称太长,可以在表名后面使用' as 简写名'或' 简写名',为表起个临时的简写名称

栗子:

/*查询学生的姓名、平均分*/
select students.sname,avg(scores.score)
from scores
inner join students on scores.stuid=students.id
group by students.sname;

子查询
子查询指的是查询的嵌套

select sname,
(select sco.score from scores sco inner join subjects sub on sco.subid=sub.id where sub.stitle='语文' and stuid=stu.id) as 语文,
(select sco.score from  scores sco inner join subjects sub on sco.subid=sub.id where sub.stitle='数学' and stuid=stu.id) as 数学,
(select sco.score from  scores sco inner join subjects sub on sco.subid=sub.id where sub.stitle='英语' and stuid=stu.id) as 英语
from students stu;

内置函数

字符串函数

  1. 查看字符的ascii码值ascii(str),str是空串时返回0 select ascii('a')
  2. 查看ascii码值对应的字符char(数字) select char(97);
  3. 拼接字符串concat(str1,str2...) select concat(12,34,'ab');
  4. 包含字符个数length(str) select length('abc');
  5. 截取字符串 left(str,len)返回字符串str的左端len个字符
  6. 截取字符串 right(str,len)返回字符串str的右端len个字符
  7. 截取字符串 substring(str,pos,len)返回字符串str的位置pos起len个字符 select substring('abc123',2,3);
  8. 去除空格 ltrim(str)返回删除了左空格的字符串str
  9. 去除空格 rtrim(str)返回删除了右空格的字符串str
  10. 去除空格 trim([方向 remstr from str)返回从某侧删除remstr后的字符串str,方向词包括both、leading、trailing,表示两侧、左、右 select trim(both 'x' FROM 'xxxbarxxx');
  11. 返回由n个空格字符组成的一个字符串space(n) select space(10);
  12. 替换字符串replace(str,from_str,to_str) select replace('abc123','123','def');
  13. 大小写转换,函数如下 lower(str) upper(str) select lower('aBcD');

数学函数

  1. 求绝对值abs(n) select abs(-32);
  2. 求m除以n的余数mod(m,n),同运算符% select mod(10,3);
  3. 地板floor(n),表示不大于n的最大整数 select floor(2.3);
  4. 天花板ceiling(n),表示不小于n的最大整数 select ceiling(2.3);
  5. 求四舍五入值round(n,d),n表示原数,d表示小数位置,默认为0 select round(1.6);
  6. 求x的y次幂pow(x,y) select pow(2,3);
  7. 获取圆周率PI() select PI();
  8. 随机数rand(),值为0-1.0的浮点数 select rand();

日期时间函数

year(date)返回date的年份(范围在1000到9999)
month(date)返回date中的月份数值
day(date)返回date中的日期数值
hour(time)返回time的小时数(范围是0到23)
minute(time)返回time的分钟数(范围是0到59)
second(time)返回time的秒数(范围是0到59)

select year('2016-12-21');
select date_format('2016-12-21','%Y %m %d');
/*当前日期current_date()*/
select current_date();
/*当前时间current_time()*/
select current_time();
/*当前日期时间now()*/
select now();

视图

对于复杂的查询,在多次使用后,维护是一件非常麻烦的事情,视图本质就是对查询的一个封装,类似Javascript中的function一样,对某一个功能的封装

/*定义视图*/
create view stuscore as 
select students.*,scores.score from scores
inner join students on scores.stuid=students.id;

/*视图的用途就是查询*/
select * from stuscore;

事务

当一个业务逻辑需要多个sql完成时,如果其中某条sql语句出错,则希望整个操作都退回,使用事务可以完成退回的功能,保证业务逻辑的正确性

银行转账是经典的解释事务的例子。用户A给用户B转账5000元主要步骤可以概括为如下两步。
第一,账户A账户减去5000元;
第二,账户B账户增加5000元;
这两步要么成功,要么全不成功,否则都会导致数据不一致。

事务四大特性(简称ACID)

  1. 原子性(Atomicity):事务中的全部操作在数据库中是不可分割的,要么全部完成,要么均不执行
  2. 一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致
  3. 隔离性(Isolation):事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的
  4. 持久性(Durability):对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障

事务语句

开启begin;
提交commit;
回滚rollback

乐观锁和悲观锁

悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。


离岛
588 声望79 粉丝