SQL基础
之后学习SQL语句都是运行在MySQL上
数据类型
Mysql将数据类型分为三大类:
1.数值类型
2.字符串类型
3.日期类型
整数型
- 存放整型的数据:在SQL中,需要更多考虑磁盘空间,系统将整数类型又分为五类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
191.tinyint:迷你型 类似byte 最大:127
2.smallint:小整型 2个字节 最大:65535
3.mediumint:中整型 3个字节
4.int:标准整型 4个字节 (使用最多的)
5.bigint:大整型 8个字节
---创建一张整型表
create table my_int(
int_1 tinyint,
int_2 smallint,
int_3 mediumint,
int_4 int,
int_5 bigint
);
---向表中插入值
正常插入
insert into my_int values(-128,32767,100000,100000,100000);
浮点型
- SQL中:将小数类型分为两种,浮点型,定点型。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17浮点型:
1.float
单精度 4个字节 精度小,会丢失精度
2.double
双精度 8个字节 精度大,15位左右。
3.decimal
定点型 8个字节 小数点固定,精度固定,绝对保证整数部分不会丢失。
---创建一张表
create table my_decimal(
float_f1 float(10,2),
double_d1 double(10,2),
decimal_d2 decimal(10,2)
);
--正常插入
insert into my_decimal values(99999999.99,99999999.99,99999999.99);
时间日期类型
1 | datetime:时间日期,格式 yyyy-MM-dd HH:mm:ss 公元 |
字符串类型
- Mysql中字符串类型被划分为六类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28char:定长
char(18):磁盘在定义结构的时候,就已经确定数据的存储长度
varchar:变长
varchar(20):按照实际数据量进行磁盘空间分配,实际使用多少,就是多少。 字符长度
text :文本字符串
text:一般超过255长度字节的都用text
blob :二进制存储
blob:存储文本二进制
enum :枚举
enum('男','女','未知','保密'):限定数据
set :集合
set('男','女','未知','保密'):多值,不能插入没有的数据
---创建一张表
create table my_string(
c_1 char(11),
v_1 varchar(10),
t_1 text,
b_1 blob,
e_1 enum('男','女','未知','保密'),
s_1 set('足球','橄榄球','拳击')
);
---正常插入
insert into my_string values('13914767897','我爱你小芳','自我介绍一下,我是大炮,今年23岁,来自祖安...','基兰,露露,女枪','男','足球,拳击');
---错误。
insert into my_string values('13914767897','我爱你小芳','自我介绍一下,我是大炮,今年23岁,来自祖安...','基兰,露露,女枪','男','橄榄球');
链接数据库
登录:
1 | mysql -uroot -p |
退出:
1 | quit 和 exit |
登录成功后,输入如下命令查看效果
1 | 查看版本:select version(); |
数据库操作
查看所有数据库
1 | show databases; |
使用数据库
1 | use 数据库名; |
查看当前使用的数据库
1 | select database(); |
创建数据库
1 | create database 数据库名 charset=utf8; |
删除数据库
1 | drop database 数据库名; |
约束
概念:对即将进入数据库的数据加以限制。
约束的分类:
- 主键约束
primary key
- 外键约束
foreign key(XXXX)references(XXXX)
- 唯一约束
unique
- 非空约束
not null
- 检查约束【Mysql已经不支持】
- 自增长
auto_increment
- 默认
default
- 枚举
enum('YYYY','XXXX')
创建表时添加约束
例子:
1 | ---班级表【主表】 |
创建表之后添加约束
例子:
1 | ---添加addr字段 |
表操作
查看当前数据库中所有表
1 | show tables; |
查看表结构
1 | desc 表名; |
删除表
1 | drop table 表名; |
创建表
1 | 语法: |
修改表-添加字段
1 | alter table 表名 add 列名 类型; |
修改表-修改字段:重命名版
1 | alter table 表名 change 原名 新名 类型及约束; |
修改表-修改字段:不重命名版
1 | alter table 表名 modify 列名 类型及约束; |
修改表-删除字段
1 | alter table 表名 drop 列名; |
查看表的创建语句
1 | show create table 表名; |
增删改查(curd)
curd的解释: 代表创建(Create)、更新(Update)、读取(Retrieve)和删除(Delete)
由于查询语句过多且经常用后续会新开一章记录
增加
说明:主键列是自动增长,但是在全列插入时需要占位,通常使用0或者 default 或者 null 来占位,插入成功后以实际数据为准。
全列插入
值的顺序与表中字段的顺序对应
1 | insert into 表名 values(...) |
部分列插入
值的顺序与给出的列顺序对应
1 | insert into 表名(列1,...) values(值1,...) |
全列多行插入
值的顺序与给出的列顺序对应
1 | insert into 表名 values(...),(...)...; |
删除
一般推荐逻辑删除
1 | delete from 表名 where 条件 |
逻辑删除
只显示客户需要看的东西,本质就是修改操作
1 | ---设置一个属性,1代表给客户看,0代表不给客户看。 |
修改
1 | update 表名 set 列1=值1,列2=值2... where 条件 |
备份
运行mysqldump命令
1 | mysqldump -u用户名 -p 需要备份的数据库名 > sql文件 |
恢复
连接mysql,创建新的数据库
退出连接,执行如下命令
1 | mysql -u用户名 –p 新数据库名 < sql文件 |
视图
问题:对于复杂的查询,往往是有多个数据表进行关联查询而得到,如果数据库因为需求等原因发生了改变,为了保证查询出来的数据与之前相同,则需要在多个地方进行修改,维护起来非常麻烦
概念:通俗的讲,视图就是一条SELECT语句执行后返回的结果集。视图是对若干张基本表的引用;是一张虚表,查询语句执行的结果,不存储具体的数据(基本表数据发生了改变,视图也会跟着改变);
主要作用
方便操作,特别是查询操作
减少复杂的SQL语句,增强可读性。
提高了重用性,就像一个函数
对数据库重构,却不影响程序的运行
提高了安全性能,可以对不同的用户
让数据更加清晰定义视图
1
2
3约定俗成,建议以v_开头
create view 视图名称 as select语句;查看视图
1
2
3查看表会将所有的视图也列出来
show tables;
索引
问题:当数据量到达千万或以上级别时,查询效率便会逐渐下降。
遇到最多、最容易出问题还是一些复杂的查询操作,所以查询语句的优化显然是重中之重。
概念:索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库的查询速度。
原理:类似二叉树。
例子:如果1000条数据,1到100分成第一段,101到200分成第二段,201到300分成第三段……这样查第250条数据,只要找第三段就可以了,一下子去除了90%的无效数据。
注意事项:
索引不是越多越好,建立太多的索引将会影响更新和插入的速度,因为它需要同样更新每个索引文件。对于一个经常需要更新和插入的表格,就没有必要为一个很少使用的where字句单独建立索引了,对于比较小的表,排序的开销不会很大,也没有必要建立另外的索引。
建立索引会占用磁盘空间。
如何使用
- 查看索引
1
2show index from 表名;
- 创建索引
如果指定字段是字符串,需要指定长度,建议长度与定义字段时的长度一致
字段类型如果不是字符串,可以不填写长度部分1
create index 索引名称 on 表名(字段名称(长度))
- 删除索引
1
drop index 索引名称 on 表名;
事务
生活例子:
A用户和B用户是银行的储户,现在A要给B转账500元,那么需要做以下几件事:
检查A的账户余额>500元;
A 账户中扣除500元;
B 账户中增加500元;
正常的流程走下来,A账户扣了500,B账户加了500,皆大欢喜。
那如果A账户扣了钱之后,系统出故障了呢?A白白损失了500,而B也没有收到本该属于他的500。
以上的案例中,隐藏着一个前提条件:A扣钱和B加钱,要么同时成功,要么同时失败。事务的需求就在于此
概念:所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。
事务四大特性(简称ACID)
一个很好的事务处理系统,必须具备这些标准特性:
- 原子性(Atomicity)
一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作,这就是事务的原子性 - 一致性(Consistency)
数据库总是从一个一致性的状态转换到另一个一致性的状态。(在前面的例子中,一致性确保了,即使在执行第三、四条语句之间时系统崩溃,支票账户中也不会损失200美元,因为事务最终没有提交,所以事务中所做的修改也不会保存到数据库中。) - 隔离性(Isolation)
通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的。(在前面的例子中,当执行完第三条语句、第四条语句还未开始时,此时有另外的一个账户汇总程序开始运行,则其看到支票帐户的余额并没有被减去200美元。) - 持久性(Durability)
一旦事务提交,则其所做的修改会永久保存到数据库。(此时即使系统崩溃,修改的数据也不会丢失。)
如何使用
开启事务后执行修改命令,变更会维护到本地缓存中,而不维护到物理表中。
表的引擎类型必须是innodb类型才可以使用事务,这是mysql表的默认引擎
1 | ---查看目前事务状态: |
修改数据的命令会自动的触发事务,包括insert、update、delete
而在SQL语句中有手动开启事务的原因是:可以进行多次数据的修改,如果成功一起成功,否则一起会滚到之前的数据
后台操作的命令(如:select、update等)基本上都默认执行了事务
计算列
计算列是MySQL8新特性
什么叫计算列呢?简单来说就是某一列的值是通过别的列计算得来的。例如,a列值为1、b列值为2,c列
不需要手动插入,定义a+b的结果为c的值,那么c就是计算列,是通过别的列计算得来的。
在MySQL 8.0中,CREATE TABLE 和 ALTER TABLE 中都支持增加计算列。下面以CREATE TABLE为例进行讲
解。
举例:定义数据表tb1,然后定义字段id、字段a、字段b和字段c,其中字段c为计算列,用于计算a+b的
值。 首先创建测试表tb1,语句如下:
1 | CREATE TABLE tb1( |
存储过程与函数
存储过程
语法:
1 | CREATE PROCEDURE 存储过程名(IN|OUT|INOUT 参数名 参数类型,...) |
以无输入无输出为例,查询emps所有数据,并命名叫select_all_data
1 | DELIMITER $ |
调用存储过程
语法:CALL 存储过程名(实参列表)
CALL select_all_data()
存储函数
语法:
1 | CREATE FUNCTION 函数名(参数名 参数类型,...) |
例子:创建存储函数,名称为email_by_name(),参数定义为空,该函数查询Abel的email,并返回,数据类型为字符串型。
1 | DELIMITER // |
调用SELECT email_by_name();
区别
关键字 | 调用语法 | 返回值 | 应用场景 | |
---|---|---|---|---|
存储过程 | PROCEDURE | CALL 存储过程() | 理解为有0个或多个 | 一般用于更新 |
存储函数 | FUNCTION | SELECT 函数() | 只能是一个 | 一般用于查询结果为一个值并返回时 |
窗口函数
8版本的新特新
特点:分组,但不聚合。
小结:窗口函数的特点是可以分组,而且可以在分组内排序。另外,窗口函数不会因为分组而减少原表中的行
数,这对我们在原表数据的基础上进行统计和排序非常有用。
公用表表达式
8版本的新特新
公用表表达式(或通用表表达式)简称为CTE(Common Table Expressions)。
CTE是一个命名的临时结果集,作用范围是当前语句。CTE可以理解成一个可以复用的子查询,当然跟子查询还是有点区别的,CTE可以引用其他CTE,但子查询不能引用其他子查询。所以,可以考虑代替子查询。
依据语法结构和执行方式的不同,公用表表达式分为 普通公用表表达式
和 递归公用表表达式
2 种。
公用表表达式的作用是可以替代子查询,而且可以被多次引用。
递归公用表表达式对查询有一个共同根节点的树形结构数据非常高效,可以轻松搞定其他查询方式难以处理的查询。
课外拓展:汉诺塔算法