1. 数据库的介绍和环境搭建
1.1 数据库介绍
1.1.1 数据存储
-
传统记录数据的缺点:
- 不易保存
- 备份困难
- 查找不便
-
现代化手段——文件
- 对于数据容量较大的数据,不能够很好的满足,而且性能较差
- 不易扩展
-
数据库:
-
持久化存储
-
读写速度极高
-
保证数据的有效性(通过约束条件来保证)
-
对程序的支持性非常好,容易扩展
-
关系型数据库
- 关系型数据库,是指采用了关系模型来组织数据的数据库,其以行和列的形式存储数据,以便于用户理解,关系型数据库这一系列的行和列被称为表,一组表组成了数据库。
- 包括MySQL、Oracle、MsSqlserver等等。
- 设计原则:
- 命名规范化
- 数据的一致性和完整性
- 减少数据冗余
- 范式理论(3NF)
- 优点:
- 复杂查询可以用SQL语句方便的在一个表以及多个表之间做非常复杂的数据查询。
- 事务支持使得对于安全性能很高的数据访问要求得以实现。
-
非关系行数据库
- 非关系型数据库主要是基于“非关系模型”的数据库(由于关系型太大,所以一般用“非关系型”来表示其他类型的数据库)
- 类型:
- 列模型:存储的数据是一列列的。关系型数据库以一行作为一个记录,列模型数据库以一列为一个记录。(这种模型,数据即索引,IO很快,主要是一些分布式数据库)——Hbase
- 键值对模型:存储的数据是一个个“键值对”,比如name:liming,那么name这个键里面存的值就是liming——redis,MemcacheDB
- 文档类模型:以一个个文档来存储数据,有点类似“键值对”。——mongoDB
- 优点:
- 性能NOSQL是基于键值对的,可以想象成表中的主键和值的对应关系,而且不需要经过SQL层的解析,所以性能非常高。
- 可扩展性同样也是因为基于键值对,数据之间没有耦合性,所以非常容易水平扩展。
-
1.1.2 理解数据库
数据列:字段
数据行:记录
数据表:数据行的集合
数据库:数据表的集合
单元格:存储的数据
ID主键:能够唯一标识某个记录的
外键:字段所存储的数据是别的表的主键
1.1.3 MySQL
- 简介:MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,后被Sun公司收购,Sun公司后来又被Oracle公司收购,目前属于Oracle旗下产品
- 特点:
- 使用C和C++编写,并使用了多种编译器进行测试,保证源代码的可移植性
- 支持多种操作系统,如Linux、Windows、AIX等
- 为多种编程语言提供了API,如C、C++、Python、Java等
- 支持多线程,充分利用CPU资源
- 优化的SQL查询算法,有效提高查询速度
- 提高多语言支持,常见的编码如GB2312、BIG5、UTF8
- 提供TCP/IP、ODBC和JDBC等多种数据库连接途径
- 提供用于管理、检查优化数据库操作的管理工具
- 大型的数据库,可以处理上千万条记录
- 支持多种储存引擎
- MySQL使用标准的SQL数据语言形式
- MySQL是可以定制的,采用了GPL协议,你可以修改源代码来开发自己的MySQL系统
- MySQL软件采用了双授权政策,分为商业版和社区版,由于其体积小、速度快、总体拥有成本低,尤其是开放源代码这一特点,一般中小型网站的开发都选择MySQL作为网站数据库
- 复制全局事务标识
- 复制无崩溃从机
- 复制多线程从机
- 在线DDL更改功能
- 存数据——快、持久化存储、数据有效性、扩展好
1.2 环境搭建
https://blog.youkuaiyun.com/sinat_34066134/article/details/120565937
2. 数据类型及约束
2.1 SQL介绍&常见的数据类型
2.1.1 SQL
- 结构化查询语言(Structured Query Language)简称SQL,是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统。
当前关系型数据库都支持使用SQL语言进行操作,也就是说可以通过SQL操作Oracle,SQL server,MySQL等关系型数据库。 - SQL语句主要分为
- DQL:(data query language)数据查询语言,用于对数据进行查询,如select
- DML:(data manipulation language)数据操作语言,对数据进行增加、修改、删除,如insert、update、delete
- DDL:( data definition language)数据定义语言,进行数据库、表的管理等,如create、drop
- 重点是数据的crud(增删改查),必须熟练编写DQL、DML,能够编写DDL完成数据库、表的操作
2.1.2 数据完整性
在表中为了更加准确的存储数据,保证数据的正确有效,可以在创建表的时候,为表添加一些强制性的验证,包括数据字段的类型、约束
2.1.3 常见的数据类型
- 数值类型
- 整数类型:int=integer
- tinyint
- smallint
- mediumint
- int/intger
- bigint
- 定点数:decimal和numeric
decimal(M,D)其中M表示十进制数字总的个数,D表示小数后面数字的位数
如decimal(5,2)表示共存5位数,小数占2位,即XXX.XX - 浮点数:float,double和real
- BIT:bit
- 整数类型:int=integer
- 字符串类型
-
char和varchar类型
charhe varchar类型声明的长度表示你想要保存的最大字符数
char表示固定长度的字符串,如char(3),如果填充“ab”时会不一个空格为“ab ”
varchar表示可变长度的字符串,如varchar(3),填充“ab”时就会存储“ab”- binary和varbinary类型
-
blob和text类型
blob是一个二进制大对象,可以容纳可变数量的数据
有四种blob类型:tinyblob,blob,mediumblob,longblob
有四种text类型:tinytext,text,mediumtext,longtext -
enum类型
enum是一个字符串对象,其值来自表创建时在列规定中显式枚举的一列值。
如size enum(‘x-small’,‘small’,medium’,‘large’,‘x-large’)
如果输入的不是枚举值,可以插入空字符串""或NULL或第1个元素:- 如果你将一个非法值enum是一个字符串对象,其值来自表创建时在列规定中显式枚举的一列值。 如size enum(‘x-small’,‘small’,medium’,‘large’,‘x-large’)ENUM(也就是说,允许的值列之外的字符串),将插入空字符串以作为特殊错误值。该字符串与“普通”空字符串不同,该字符串有数值值0。
- 如果将ENUM列声明为允许NULL,NULL值则为该列的一个有效值,并且默认值为NULL。
- 如果ENUM列被声明为NOT NULL,其默认值为允许的值列的第1个元素。
-
set类型
set是一个字符串对象,可以有零或多个值,其值来自表创建时规定的允许的一列值
例如指定为set(‘one’, ‘two’) NOT NULL的列可以有下面的任何值:- ’ ’
- ‘one’
- ‘two’
- ‘one,two’
SET值按数字顺序排序。NULL值排在非NULL SET值的前面
blob和text与varbinary和varchar的相似点:
-
blob列被视为二进制字符串。text列被视为字符字符串,类似char和binary。
-
在大多数方面,可以将blob列视为能够足够大的varbinary列。同样,可以将text列视为varchar列。
-
当保存或检索blob和text列的值时不删除尾部空格。(这与varbinary和varchar列相同)。
不同点:
- 比较时将用空格对text进行扩充以适合比较的对象,正如char和varchar。
- 对于blob和text列的索引,必须指定索引前缀的长度。对于char和varchar,前缀长度是可选的。
- blob和text列不能有默认值。
binary和varbinary类型类似于char和varchar类型,但是不同的是,它们存储的不是字符字符串,而是二进制串。所以它们没有字符集,并且排序和比较基于列值字节的数值值。
-
- 日期时间类型
-
date、datetime、timestamp类型
date:用’YYYY-MM-DD’格式检索和显示,支持的范围是’1000-01-01’到 ‘9999-12-31’。
datetime:以’YYYY-MM-DD HH:MM:SS’格式检索和显示,支持的范围为’1000-01-01 00:00:00’到’9999-12-31 23:59:59’。
timestamp:包含日期和时间,范围从’1970-01-01 00:00:01’ UTC 到’2038-01-19 03:14:07’ UTC。
函数返回的结果,其值适合DATETIME、DATE或者TIMESTAMP上下文,例如NOW()或CURRENT_DATE。
-
time类型
MySQL以’HH:MM:SS’格式检索和显示time值(或对于大的小时值采用’HHH:MM:SS’格式)。
范围可以从’-838:59:59’到’838:59:59’。
小时部分会因此大的原因是TIME类型不仅可以用于表示一天的时间(必须小于24小时),还可能为某个事件过去的时间或两个事件之间的时间间隔(可以大于24小时,或者甚至为负)。
-
year类型
year类型是一个单字节类型用于表示年
MySQL以YYYY格式检索和显示YEAR值。范围是1901到2155。
-
- 几何类型
- 其他多媒体相关
对于图片、音频、视频等文件,不存储在数据库中,而是上传到某个服务器上,然后在表中存储这个文件的保存路径
2.1.4 各种数据类型占用的存储
-
数值类型
取够用的就行,尽量减小存储空间类型 字节大小 有符号范围(Singed) 无符号范围(Unsinged) TINYINT 1 -128~127 0-255 SMALLINT 2 -32768~32768 0~65535 MEDIUMINT 3 -8388608~8388607 0~16777215 INT/INTEGER 4 -2147483648~2147483647 0-4294967295 BIGINT 8 -9223372036854775808~
92233720368547758070~
18446744073709551615 -
字符串类型
类型 大小 用途 CHAR 0-255 bytes 定长字符串 VARCHAR 0-65535 bytes 变长字符串 TINYBLOB 0-255 bytes 不超过 255 个字符的二进制字符串 TINYTEXT 0-255 bytes 短文本字符串 BLOB 0-65 535 bytes 二进制形式的长文本数据 TEXT 0-65 535 bytes 长文本数据 MEDIUMBLOB 0-16 777 215 bytes 二进制形式的中等长度文本数据 MEDIUMTEXT 0-16 777 215 bytes 中等长度文本数据 LONGBLOB 0-4 294 967 295 bytes 二进制形式的极大文本数据 LONGTEXT 0-4 294 967 295 bytes 极大文本数据 -
日期时间类型
类型 大小 ( bytes) 范围 格式 用途 DATE 3 1000-01-01/9999-12-31 YYYY-MM-DD 日期值 TIME 3 ‘-838:59:59’/‘838:59:59’ HH:MM:SS 时间值或持续时间 YEAR 1 1901/2155 YYYY 年份值 DATETIME 8 1000-01-01 00:00:00/9999-12-31 23:59:59 YYYY-MM-DD HH:MM:SS 混合日期和时间值 TIMESTAMP 4 1970-01-01 00:00:00/2038 结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07 YYYYMMDD HHMMSS 混合日期和时间值,时间戳
2.2 数据库约束
主键 primary key:物理上存储的顺序,必须非空。只有主键才有自增属性
非空 not null:此字段不允许null
唯一 unique:此字段的值不允许重复
无符号 unsigned:非负数
默认 default:当不填写时使用默认值(在索引中设置)
自增 auto_increment:插入新数据时,插入数据时无需设置此列,默认将自增,表中只有一个自增,中间项被删除后仍按原顺序增加
外键 foreign key:对关系字段进行约束,当为关系字段填写值时,会到关联的表中查询此值是否存在,如果存在则填写成功,如果不存在则填写失败并抛出异常
3. 数据库与数据表的基本操作
3.1 数据库操作
-
数据库的连接——mysql -uroot -p或mysql -u root -proot(不推荐,不安全)连接后可直接看到数据库的版本
-
显示数据库版本——select version()
-
查看所有数据库——show databases;
-
显示时间——show now();
-
退出数据库——exit 或 quit
-
创建数据库——create database 数据库名 charset=utf8;
-
使用数据库——use 数据库名;
-
查看创建数据库的命令——show create database 数据库名;
-
查看当前使用的数据库——select database();
-
删除数据库——drop database 数据库名;【不可使用!!】
sql语句最后需要有分号;结尾 MySQL不区分大小写
3.2 数据表操作
-
查看当前数据库中所有表-show tables;
-
创建表
-
查看表结构
-
查看表的创建语句
-
删除表
-
推出表
-
示例:
创建students表(id,name,age,high,gender,cls_id)
create table students(
id int primary key not null auto_increment,
name varchar(30),
age tinyint unsigned default18,High decimal(5,2)
gender enum(“男”,“女”)default“保密”,
cls_id tinyint
);
-
修改表-添加字段
-
修改表-修改字段:不重命名-
-
修改表-修改字段:重命名-
-
修改表-删除字段:alter table 表名 drop 列名
4. 数据的基本操作:增删改查
4.1 新增
4.1.1 全列插入
insert into 表名 values(…)
…表示按列名顺序输入信息,数据之间用逗号隔开,中文加上引号。
示例:
向students表中插入一个学生信息:
insert into students values(0,‘shell’,20,181,‘男’,2)
主键字段用0/null/default来占位
若插入的是别的函数得到的结果集,则不需要使用values()
insert into 表名(列名)【结果集】;
insert into 表名(字段) select 字段名 from 表名 …
4.1.2 枚举类型插入
向students表中插入一个学生信息insert into students values(null,‘shell’,20,181,1,2);
此时gender的插入没有用’男’,而是用了数字1
4.1.3 部分插入
insert into 表名(列1,…) values(值1,…);
insert into students(`name`,`gender`) values(‘shell’,1)
想要部分插入成功,【非空】且【无默认值】约束的列名必须要有信息输入
4.1.4 多行插入
insert into 表名 values(…),(…),(…);
insert into students values(0,‘shell’,20,181,‘男’,2),(0,‘shell’,20,181,1,2),(0,‘666’,20,181,‘男’,2);
4.2 删除
4.2.1 物理删除
delete from 表名 where 条件;
将students表中id = 3 的记录删掉
delete from students where id=3;
删除的是数据,几乎不这么操作
4.2.2 逻辑删除
由于直接删除数据无法找回原来的记录,所以添加字段is_delete用1(是)0(否)表示是否删除;
需要删除一个记录时直接将其is_delete列数据修改为1即可
数据不是被删除了,而是被隐藏了
在students表中新建is_delete字段
alter table add is_delete tinyint default 0 comment‘0是为删除,1是已删除’;
将id=4的记录删除
update students set is_delete=1 where id=4;
查找表 students所有被删除的字段
select * from students where is_delete=1;
4.3 修改
语法:update 表名 set 字段1=新值1,字段2=新值2… where 条件;
不加where条件时,全部都会发生改变!
将名字为shell的改为python
update students set name=‘python’ where name=‘shell’
将id=3的姓名及年龄做修改
update students set name=‘none’,age=19 where id=3;
5. MySQL查询
5.1 基本语法
查询完成语法:
select 去重选项 字段列表 [as 字段别名] from 数据源 [where子句] [group by 子句] [having子句] [order by 子句] [limit子句];
- 查询所有字段
- 查询指定字段
- 使用as给字段起别名
- 可以通过as给表起别名
- 在select后面列前使用distinct可以消除重复行
5.2 简单查询
-
查询所有列-select * from 表名;
-
查询指定列-select 列1,列2,… From 表名;
select name,age,gender from students -
去重复字段的查询-select distinct 列1,列2 ,… from 表名;
查询students表中所有不同的名字
select distinct name from students;
distinct去重,当查询多列时,只有当所查找的列名1,列名2…内容都相同才会只显示一条(即整个查询的行是否重复) -
使用as为查询的结果的列或表指定别名
当一些字段名称或者表名称太长或者过于复杂可以为其取别名。一般两个表联合查询时才会给表取别名。列如,将查询结果中的name显示为姓名
select name as 姓名 ,age ,gender from students where name = ‘shell’;(条件中依旧是原名称name)
5.3 条件查询
5.3.1 基本语法
- 语法:
select … from 表名 where 条件 ; - 示例:
select name from students where id=3;
select * from students where name<>“shell”; - having条件表达式:用来分组查询后指定一些条件来输出查询结果
having作用和where一样,where作用原始数据集;having用作于分组后的结果集
5.3.2 比较运算符
比较运算符:
- 等于=
- 大于>
- 大于等于>=
- 小于<
- 小于等于<=
- 不等于 !=或<>
条件写成类似于18<age<28无意义,不会报错,但按默认没加盖条件的情况运行
5.3.3 逻辑运算符
逻辑运算符:
-
and交——查询18岁以上的女性select * from students where age>18 and gender=‘女’;
-
or并——查询编号小于4或没被删除的学生select * from students where id<4 or is_delete=0;
-
not取反,补——加括号以确定优先级,括号里的先计算
查询不是18岁女性的学生select * from students where not (age=18 and gender=‘女’);
查询年龄不是18岁的女性select * from students where not age=18 and gender=2;MySQL数据库中优先级:not>and>or,一般通过加括号的形式解决,且可读性更高。
5.3.4 模糊查询
-
like
-
like’…’
%表示任意个字符串
_表示一个字符串 -
查询姓名以“小”开始的学生信息select * from students where name like ‘小%’;
查询姓名有“小”的学生信息select * from students where name like’%小%’;
查询姓名是两个字的学生信息select * from students where name like’__’;
查询姓名至少是两个字的学生信息select * from students where name like’__%’;
-
数据量大时不使用,like的使用效率低。
-
-
rlike
用法与like相同,但rlike支持正则表达式- 正则表达式:正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。
. 匹配任意单个字符串
* 匹配0个或多个前一个得到的字符
[] 匹配任意一个[]内的字符,[ab]*可以匹配空字符串、a、b、或由任意个a和b组成的字符串。
^ 匹配开头,如^s匹配以s开头的字符串
$ 匹配结尾,如s$匹配以s结尾的字符串
{n} 匹配前一个字符反复n次 - 查询姓名以周开始的学生信息select * from students where name rlike"^周.*";
查询姓名以周开始、伦结尾的学生信息select * from students where name rlike"^周.*伦$";
- 正则表达式:正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。
5.3.5 范围查询
-
in表示在一个非连续范围内
not in不非连续的范围之内
**between…and…**表示在一个连续的范围内
not between…and…表示不在一个连续的范围内
-
查询年龄为18、34的姓名select name,age from students where age in(18,34);
-
查询姓名不是shell、python的学生信息 select * from students where name not in(‘shell’,‘python’);
-
查询id是2到5的男生信息select * from students where id between 2 and 5 and gender=‘男’;
(超出边界不会报错,会返回当前到信息的终点)
- 查询年龄不在18到34的男生信息select * from students where (age not between 18 and 34) and gender=1;
5.3.6 空判断
判空is null
判非空is not null
注意:
-
不能用=
-
null(占用空间地址的)于“”(空字符串,不占用空间地址)是不同的
查询姓名信息为空的男生信息select * from students where name is null and gender=1;
5.4 聚合函数
- 基础函数
- Count(*)总数
- max(列)最大值
- min(列)最小值
- sum(列)求和
- avg(列)平均值
- round(123.45,1) 四舍五入,保留一位小数
- 示例
查询学生总数select count(*) as 总人数 from students;
查询男生有多少人select count(*) as 男生人数 from students where gender=1;
查询女生最大的年龄select max(age) from students where gender=2;
查询最大年龄的女生姓名select id from students where max(age) and gender=2;
需要用到子查询select name from students where gender=2 and age=(select max(age) from students where gender=2)
查询未删除学生的最小编号 select min(id) from students where is_delete=0;
查询男生的年龄和select sum(age) from students where gender=1;
查询未删除女生年龄的平均值select avg(age) from students where gender=2 and is_delete=0;
计算平均年龄,保留两位小数select round(avg(age),2) from students;或者select round(sum(age)/count(*),2) from students;
5.5 分组
-
Group by
-
group by的含义:将查询结果按照1个或者多个字段进行分组,字段值相同的为一组
group by可用于单个字段分组,也可用于多个字段分组 -
语法:
-
select …字段1 from 表名 group by 字段;
…字段1 一般于集合函数共同使用,且字段1是真正能区分这个组的字段-
示例:按照性别分组,查询所有性别select gender from students group by gender;
计算男生和女生的人数select gender as 性别,count(*) from students group by gender;
男女同学的最大年龄select gender as 性别,max(age) from students group by gender;
-
-
-
-
Group by + group_concat()
group_concat(字段名)可以作为一个输出字段来使用
表示分组之后,根据分组结果,使用group_concat()来放置每一组的某字段的值的集合- 查询同性别学生的姓名select gender as 性别,group_concat(name) from students group by gender;
查询同性别学生的姓名,年龄select gender as 性别,group_concat(‘姓名’,name,’_’,‘年龄’,age) from students group by gender;
‘‘姓名’,’_’,'年龄’目的是间隔开两个字段的信息或加以标识,用别的符号/蚊子等也可,字段前后的可以加。(相当于python中的字符串拼接)
- 查询同性别学生的姓名select gender as 性别,group_concat(name) from students group by gender;
-
Group by + 集合函数
通过group_concat()的启发,我们既然可以统计出每个分组的某字段的值的集合,那么我们也可以通过集合函数来对这个值的集合做一些操作 -
group by + having
查询人数大于5的性别的人数select gender,count(*) from students group by gender having count(*)>5;
查询人数大于5的性别的人姓名select gender,count(*),group_concat(name) from students group by gender having count(*)>5;
查询平均年龄超过18岁的性别及姓名select gender,group_concat(name),avg(age) from students group by gender having avg(age)>18;
5.6 排序
目的:为了方便查看数据,可以对数据进行排序
语法:select * from 表名 order by 列1 asc|desc [,列2 asc|desc,…];
说明:
-
将行数据按照列1进行排序,如果某些行列1的值相同时,则按照列2排序,以此类推
-
默认按照列值从小到大排列(asc)
-
asc从小到大排列,即升序
-
desc从大到小排序,即降序
- 查询年龄在18到26岁之间的男同学,按照年龄从小到大排序
select * from students where gender=1 and (age between 18 and 26) order by age;
- 查询年龄在18到34岁之间的女同学,按照身高从高到矮排序
select * from students where gender=2 and (age between 18 and 34) order by high desc;
- order by 多个字段
例如,
查询年龄在18到28岁之间的女性,年龄从大到小排序,如果年龄相同的情况下按照身高从小到大排序
select * from students where gender=2 and (age between 18 and 28) order by age desc,high;
按照年龄从小到大,身高从低到高排序
select * from students order by age as c,high as c;
5.7 分页
目的:获取部分行,当数据量过大时,在一页中查看数据非常麻烦
语法:select * from 表名 limit start,count;
说明:
- 从start开始(从0开始),获取count条数据【起始位置(从0开始),数据个数】
- start,count不能写数学公式
- limit 只能写到SQL语句最后,只限制显示的条数
查询前5个数据select * from students limit5;
查询id 6-10(包含)的数据select * from students limit 5,5;
制作分页——limit (第N页-1)*每页显示的个数,每页显示的个数
每页显示2个,第1个页面select * from students limit 0,2;
每页显示2个,第2个页面select * from students limit 2,2;
每页显示2个,第3个页面select * from students limit 4,2;
每页显示2个,第4个页面select * from students limit 6,2;
5.8 连接查询
连接查询: 当查询结果的列来源于多张表时,需要将多张表连接成一个大的数据集,再选择合适的列返回。
语法:select * from 表1 inner或者left或者right join 表2 on 表1.列 = 表2.列;
mysql支持三种类型的连接查询:
-
内嵌连接:查询的结果为两个表匹配到的数据
列如:
查询能够对应半截的学生以及班级信息(含classes表中的id等)
select * from students inner join classes on students.cls_id=classes.id;
查询能够对应班级的学生以及班级信息,显示学生的所有信息,只显示班级名称(不含classes表中的id等)
select s.*,c.name from students as s inner join classes as c on s.cls_id=c.id 查询有能够对应班级的学生的姓名班级
select students.name,classes.name from students inner join classes on students.cls_id=classes.id; -
左连接查询: 查询的结果为两个表匹配到的数据,左表特有的数据,对于右表中不存在的数据使用null填充
优化:以小表驱动大表
查询每位学生对应的班级信息
select students.name,classes.name from students left join classes on students.cls_id=classes.id;
查询没有对应班级信息的学生信息,并按id排序
select * from students as s left join classes as c on s.cls_id=c.id having c.id is null order by s.id; -
右连接查询: 查询的结果为两个表匹配到的数据,右表特有的数据,对于左表中不存在的数据使用null填充
将数据表名字互换位置,用left join完成