MySQL基础
文章目录
数据库相关概念
- DB:dataBase数据库,保存一组有组织的数据的容器,可以把数据理解成文件,这些文件由数据库统一保存处理。
- DBMS:数据库管理系统,又称为数据库软件,用于管理DB中的数据,就是咱们平时说的MySQL,Oracle。
- SQL:结构化查询语言,用于和DBMS通信的语言,简单来说就是用来操作数据库管理系统的语言,所以基本上是通用的。
SQL的语言分类
DQL(Data Query Language):数据查询语言 关键词:SELECT
DML(Data Manipulate Language):数据操作语言关键词:INSERT 、UPDATE、DELETE
DDL(Data Define Languge):数据定义语言关键词:CREAT、DROP、ALTER
TCL(Transaction Control Language):事务控制语言 关键词:COMMIT、ROLLBACK
DQL
常见函数
函数分为单行函数和分组函数,单行函数多用作处理数据,组函数用来做统计使用
单行函数
- 字符函数
concat 拼接,MySQL中的“+”只能用来做计算的加号,拼接字符串用concat
substr 截取子串,MySQL中的截取字符串索引从1开始,Java从0开始,两个参数,第一个是从哪开始,第二个是截取多少位
upper 转换成大写
lower 转换成小写
trim 去前后的空格或字符
trim() 去除首尾的空格
trim('a' from 'str') 去除str首尾的'a'
ltrim 去左边空格
rtrim 去右边空格
replace 替换
lpad 左填充
lpad('a',10,'*') 效果:*********a
lpad('abcd',2,'*') 效果:ab 超过会从右边截断
rpad 右填充
instr 返回子串在父串的起始索引,索引从1开始
length 获取字节个数
- 数学函数
round 四舍五入
Round(a,2) 保留2位小数后面的四舍五入
在Java中 负数是五舍六入
rand 随机数,随机产生0(包括0)到1(不包括1)直接的随机数
floor 向下取整 返回小于等于该参数的最大整数
ceil 向上取整 返回大于等于该参数的最小整数
mod 取余,正负号取决于分子 mod(a,b)=a-a/b*b
truncate截断
truncate(1.66,1) 结果:1.6 第二个参数表示的是小数点后几位,直接截取
- 日期函数
now 当前系统日期+时间
curdate 当前系统日期
curtime 当前系统时间
str_to_date 将字符转换成日期
date_format 将日期转换成字符 - 流程控制函数
if 处理双分支
if(boolean,'值1','值2') 和Java中的三元运算符一样的用法
case语句 处理多分支
case语句分为两种情况
#处理等值判断
case [要判断的字段或者表达式]
when [常量] then [要显示的值或者语句]
when [常量] then [要显示的值或者语句]
else [……]
……
end
#处理条件判断
case
when 条件 then [要显示的值或者语句]
when 条件2 then [要显示的值或者语句]
else [要显示的值或者语句]
end
- 其他函数
version版本
database当前库
user当前连接用户
分组函数
- sum 求和
- max 最大值
- min 最小值
- avg 平均值
- count 计数
特点:
- 以上五个分组函数都忽略null值。可以使用函数 if null(’'字段值,‘值’)将NULL转化成指定值
- sum和avg一般用于处理数值型,max、min、count可以处理任何数据类型
- 都可以搭配distinct使用,用于统计去重后的结果
- count的参数可以支持:字段,* ,常量值(一般放1),建议使用count(*),因为不管是InnoDB还是Mylsam引擎都是count(*)最快
查询类型
基础查询
- 通过select查询完的结果 ,是一个虚拟的表格,不是真实存在
- 要查询的东西可以是常量值、表达式、字段、函数
SELECT
[列名|常量|表达式|函数]
FROM
[表名] ;
条件查询
根据条件过滤原始表的数据,查询到想要的数据
SELECT
[列名|常量|表达式|函数]
FROM
[表名]
WHERE
[筛选条件] ;
条件运算符:>、<、>=、<=、=、!=、<>、<=>
<=>:安全等于 当NULL<=>NULL 时会返回TRUE
逻辑运算符: and,or,not,这三个分别等价于Java中的(&&,||,!)MySQL也支持这种写法
模糊查询
SELECT
[列名|常量|表达式|函数]
FROM
[表名]
WHERE
[列名|常量|表达式|函数] LIKE '%a%'
[列名|常量|表达式|函数] IN ('','','')
[列名|常量|表达式|函数] BETWEEN A AND B
[列名|常量|表达式|函数] IS NULL
[列名|常量|表达式|函数] IS NOT NULL
LIKE中用到的%叫做通配符
%:任意多个字符
_:任意单个字符
排序查询
SELECT
[列名|常量|表达式|函数]
FROM
[表名]
WHERE
[筛选条件]
ORDER BY
[列名|常量|表达式|函数] [ASC|DESC]
默认是升序(ASC)
分组查询
首先我们先说上面提到的分组函数,发现都是对一组或者说是大量的数据做统计操作,而分组函数默认是把查询的整张表作为一个组,所以最后的结果只有一行,而分组查询就是把查询的表通过条件割裂成不同的组,这样就可以得到不同组的统计结果。查询结果也就是多行了。也就可以理解为什么常说,分组函数后面出现的字段,必须也出现在分组查询的分组条件中,只有这样才可以保证查询结果的行数是一致的。
SELECT
[查询的字段|分组函数]
FROM
[表名]
WHERE
[筛选条件]
GROUP BY
[以哪个字段作为分组,多个字段分组,字段间以逗号分隔]
HAVING
[筛选条件]
其中WHERE关键字是对分组前的表进行筛选操作,分组后相当于是生成了一张新的表,而HAVING关键字则是对分组后的结果集进行删选,两者用法一样,只是针对的表不同。
连接查询
连接查询分为SQL92语法和SQL99语法,这里只介绍SQL99
连接查询分为
- 内连接:等值连接、非等值连接、自连接
- 外连接:左外连接、右外连接、全外连接(MySQL不支持)
- 交叉连接
外连接,外连接的场景其实是等值连接的一种特殊需求,我们把等值连接的两张表分为主表和附表,首先等值连接只会显示主表和附表中满足连接条件的数据,而外连接则是在等值连接的基础上,要求显示出主表的所有数据,包括不满足连接条件的。而左外连接和右外连接只是一个相对的概念。左外连接 LEFT JOIN的左边是主表,RIGHT JOIN的右边是主表
交叉连接的结果就是笛卡尔积
自连接只是一个概念上的说法,它的唯一特别之处就是连接的两张表是同一张表
SELECT
[列名|常量|表达式|函数]
FROM
表1
[INNER|LEFT|RIGHT|CROSS] JOIN
表2
ON
连接条件
注意如果SELECT中要查询的字段两个表中都有,则需要指定是哪一个表中的这个字段,语法是表名.列名。这时候我们可能需要别名,可以给表名,字段名起别名。
SELECT
[列名] AS [别名]
FROM
[表名] AS [别名]
子查询
一条查询语句中又嵌套了另一条完整的SELECT语句,其中被嵌套的SELECT语句,称为子查询或内查询,在外面的查询语句,称为主查询或外查询。其实简单点来说,就是将一个查询结果又作为另一个查询的数据来源或者查询条件,而根据子查询的查询结果(几行几列)又将子查询分为了下面几种
- 标量子查询(1行1列)
标量子查询的结果就是一个数值,将这个数值放在WHERE\HAVING作为筛选条件是最常见的,当然也可以直接放在SELECT后面作为一个常量输出 - 列子查询(一列多行)
而列子查询可以说是标量子查询的升级版,将一组数值作为WHERE\HAVING的筛选条件
这里讲一下多行操作符:in、any/some、all,in是指是结果集中任意一个就行,any意为任意一个,all意为所有,any和all通常会跟比大小有关可以用其他(MAX,MIN函数)方式替代。 - 行子查询(一行多列)
行子查询会会有一行多列,这多列通常是作为不同的筛选条件,但我们通常可以用别的方式实现,所以很少使用
SELECT
*
FROM
employees
WHERE
( employes_id,salary)=(
SELECT
MIN(employee_id),MAX(salary)
FROM
employees
)
-
表子查询(多行多列)
表子查询顾名思义,将查询结果作为一个新的表,作为主查询的数据来源 -
相关子查询
子查询放在exists关键字后面就是相关子查询,exists的返回值是boolean,exists后面通常跟了一个关联检索,用来返回满足关联条件或不满足(no exists)的数据,有数据就返回true,否则false,但这个false和true实际是用来控制主查询的该条数据是否作为查询结果,exists可以完成的功能in都可以完成,但是涉及效率问题,这个后面单独讲。
分页查询
分页,大家都懂
SELECT
[列名|常量|表达式|函数]
FROM
表名
LIMIT
[起始的条目索引,条目数];
条目数的意思是一页有多少条数据。
注意:
- 起始条目索引从0开始
- limit子句放在查询语句的最后
- (page-1)*siez,size
联合查询
将多条查询语句合并成一个查询结果
查询语句1
UNION
查询语句2
应用场景:结果来自多个表,并且这些表之间没有直接的连接关系,但查询的信息是一致的时候。
检索要求:查询的列数一样,类型和顺序一致
UNION默认去重,UNION ALL 可以包含重复项
DML
插入数据
INSERT INTO
[表名]
(列名,列名……)
VALUES
(值,值……),
(值,值……),
……,
(值,值……);
INSERT INTO
[表名]
SET
列名=值,
列名=值,
……
列名=值;
values支持同时插入多行数据,并且支持子查询,set插入只能插入一条数据。
values的列名可以不写,默认就是全部列名,并且是按照表的顺序的,值和列名必须一一对应
更新数据
- 单表更新
UPDATE
[表名]
SET
列名=值,
列名=值,
……
列名=值
WHERE
更新条件
更新的时候如果不加更新条件会更新表中的所有数据
- 级联更新
级联更新其实就是把两张或者多张表先关联起来然后再对关联后的表进行更新,常用于更新外键
UPDATE
表名1
[INNER|LEFT|RIGHT|CROSS] JOIN
表名2
ON
连接条件
SET
表名.字段=值,
表名.字段=值
WHERE
筛选条件
删除数据
delete语句
单表的删除
DELETE
FROM
表名
WHERE
筛选条件
不加筛选条件会删除表中所有的数据
级联删除,和级联更新一个原理
DELETE
表1,表2
FROM
表名1
[INNER|LEFT|RIGHT|CROSS] JOIN
表名2
ON
连接条件
WHERE
筛选条件
truncate语句
truncate table
表名
两种方式的区别
- truncate的意思是置空truncate不能加where条件,是清空全表,而delete可以加where条件,可以只删除部分数据
- truncate的效率高
- truncate删除带自增长的列的表后,如果再插入数据,数据从1开始,delete删除带自增长列的表后,如果再插入数据,数据从上一次的断点处开始
- truncate删除不能回滚,delete删除可以回滚
DDL
库和表的管理
库的管理
- 创建库
CREATE DATABASE
库名
- 删除库
DROP DATABASE
库名
修改库名会带来很多的麻烦,首先,INNODB不支持修改库名
MyISAM可以这样写,但是官方并不推荐,可能会丢失数据
RENAME DATABASE
olddbname
TO
newdbname
一般会建立一个新库,然后把旧库的数据重新导入,然后删除原来的旧库。再就是直接修改数据库对应的文件名。有一些数据库视图操作软件支持这个功能,再就是在Linux环境下使用脚本可以安全高效的完成这个操作,不做多的介绍。
[修改Mysql数据库名的方法]
[修改Mysql数据库名的方法]:https://blog.csdn.net/CSDN419135619/article/details/52774715
表的管理
- 创建表
CREATE TABLE
[要创建的表名]
(
[列名][列的类型][长度][约束],
[列名][列的类型][长度][约束],
……
)
- 表的复制
#仅复制结构
CREATE TABLE
[要创建的表名]
LIKE
[要复制的表名] #这是原表
#复制结构和数据
CREATE TABLE
[要创建的表名]
SELECT * FROM
[要复制的表名] #这是原表
- 删除表
DROP TABLE
[要删除的表名];
- 修改表
#修改列名
ALTER TABLE
[表名]
CHANGE COLUMN
[旧列名] [新列名] [类型];
#修改字段类型和列级约束
ALTER TABLE
[表名]
MODIFY COLUMN
[列名][类型][约束] ;
#修改表名
ALTER TABLE
[旧表名]
RENAME TO
[新表名];
#添加字段
ALTER TABLE
[表名]
ADD COLUMN
[字段名][类型] first;#这里的first表示列会添加在第一行
#删除字段
ALTER TABLE
[表名]
DROP COLUMN
[要删除的字段名];
常见数据类型
- 数值型
- 整形
有符号,不设置默认是有符号的
无符号 unsigned - 小数
定点数 精度高 dec(M,D) M代表总位数,D代表小数位
浮点数 float(M,D),double(M,D)
- 整形
- 字符型
- 较短的文本 char,varchar
- 较长的文本 text,blob(二进制)
- 日期型 date,tiem,year,datetime,timestamp
杂项:
- int(7) int类型的长度并不是能输入多大的数,而是在查询结果集中显示的长度,通常和zerofill配合使用,当字段定义为int(7) zerofill 当不满7位的时候会使用0左填充
- set类型可以存储多个字段,enum类型能存储一个,但set和enum都只能存储规定的字段
[SET 与 ENUM 类型使用详解]
[SET 与 ENUM 类型使用详解]:[https://blog.csdn.net/kxjrzyk/article/details/51731899]
六大约束
- NOT NULL:非空
- DEFAULT:默认,可以设置默认值
- UNIQUE:唯一,可以为空
- CHECK:检查约束,即输入的值要符合某种规范,MySQL不支持
- PRIMARY KEY:主键,唯一非空
- FOREIGN KEY:外键,用来限制两个表的关系,外键设在从表上,用于引用主表中某列的值,并且这个列必须是一个键
主键和唯一的区别
- 一个表至多有一个主键,但可以有多个唯一
- 主键不允许为空,唯一可以为空,但唯一的一列中不会出现两个NULL
注意事项:
约束分为列级约束和表级约束,其中列级约束中不可以添加外键,表级约束中不可以添加非空和默认
列级约束在创建表的时候,在定义字段的时候直接添加,跟在字段类型的后面
表级约束
表级约束是创建表的最后面添加
CREATE TABLE
[表名](
[列名][类型][列级约束],
[列名][类型][列级约束],
CONSTRAINT [KEYNAME] [约束类型](列名)
#添加外键 其中keyName是可以不写的
CONSTRAINT [foreign_key] foreign(列名) reference 表名(列名)
)
标识列
标识列又称为自增长列,可以不用手动的插入值,系统提供默认的序列值
CREATE TABLE
[表名](
id INT PRIMARY KEY AUTO_INCREMENT
);
特点:
- 标识列所标记的列必须是一个键
- 一个表最多只能有一个标识列
- 标识列的类型只能是数值型
- 标识列可以通过 SET auto_increment_increment=3;设置步长
#每次增长3
SET auto_increment_increment=3;
- 可以通过手动插入值,设置起始值
TCL
数据库事务
含义
通过一组逻辑操作单元(一组DML语句),将数据从一种状态切换到另外一种状态,只有InnonDB支持MySQL事务,事务只支持DML,不支持DDL
事务的特点(ACID)
- 原子性:要么都执行,要么都回滚
- 一致性:保证数据的状态操作前和操作后保持一致
- 隔离性:多个事务同时操作相同数据库的同一个数据时,一个事务的执行不受另外一个事务的干扰,这个需要通过设置事务隔离来做到
- 持久性:一个事务一旦提交,则数据将持久化到本地,除非其他事务对其进行修改
相关步骤
- 开启事务
- 编写事务的一组逻辑操作单元(多条SQL语句)
- 提交事务或回滚事务
事务的分类:
- 隐式事务,没有明显的开启和结束事务的标志,比如insert、update、delete语句本身就是一个事务
- 显式事务,具有明显的开启和结束事务的标志
#取消自动提交事务的功能
set autocommit=0;
#开启事务
start transaction
#编写事务的一组逻辑操作单元(多条SQL语句)
INSERT/DELETE/UPDATE
#提交事务或者回滚事务
commit;
rollback;
断点可以指定事务的提交和回滚的位置
set autocommit=0;
start transaction;
SQL1;
SQL2;
savepoint p1
SQL3;
#这时候SQL1,SQL2会被提交,只有SQL3会被回滚
rollback to p1
事务的隔离级别
当多个事务同时操作同一个数据库的相同数据时,会发生事务的并发问题
- 脏读:一个事务读取到了另外一个事务未提交的数据
- 不可重复读:同一个事务中,多次读取到的数据不一致。举个例子:第一次读的数据,读完之后恰好有另一个事务修改了第一次读的数据,并提交,这时候再读取就会发现和第一次的不一样
- 幻读:同一事务中,用同样的操作读取两次,得到的记录数不相同,幻读的侧重点在于两次读取的纪录数量不一致另外一个事务进行插入或者删除,导致第一个事务两次的记录数不同
通过设置事务的隔离级别来避免上面的问题
- READ UNCOMMITTED
- READ COMMITTED 可以避免脏读
- REPEATABLE READ(MySQL默认级别) 可以避免脏读、不可重复读和一部分幻读
- SERIALIZABLE可以避免脏读、不可重复读和幻读
设置事务隔离级
set [session|global] transaction isolation level
[隔离级别名];
视图
视图是什么
VIEW,是一种有结构(有行有列)但是没结果(结构中不真实存放数据)的虚拟表,虚拟表的结构来源不是自己定义,而是从对应的基表中产生(视图的数据来源)。上面有一点抽象,我来举个例子,我们在查询一张表通过各种筛选条件和分组最后得出了结果集,我们通过视图软件看这个结果集就是一张虚拟表,而我们把这张表保存起来就是视图。视图本身是没有任何数据的,他依赖于基表的数据,视图本质上保存的是检索逻辑,保存的是SQL。
为什么要使用视图
- 视图可以提高SQL的利用率,将一条复杂的查询语句使用视图进行保存,以后可以直接对视图进行操作,可以减少SQL的复杂性
- 隐藏基表,和表实现了分离,保证数据安全。视图的操作是主要针对查询的,如果对视图进行处理(删除),不会影响基表数据(相对安全)
- 可有选择的对外提供数据,视图往往是在大项目中使用,而且是多系统使用,可以对外提供有用的数据,隐藏无用的数据
怎么使用视图
创建视图
CREATE VIEW
[视图名]
AS
查询语句 #这就是视图的逻辑
修改视图逻辑
#方法1
CREATE OR REPLACE VIEW
[视图名]
AS
[视图逻辑]
#方法2
ALTER VIEW
[视图名]
AS
[视图逻辑]
删除视图
#可以一次删除多个
DROP VIEW
[视图名],[视图名],[视图名]
视图的增删改查
视图可以给他理解成一张表,对于DQL视图和表示一样的,不过对DML视图是有条件的,视图的逻辑中包含下面的关键字不可以做DML
- 逻辑SQL语句包含这些关键字:分组函数、DISTINCT、GROUP BY、HAVING、UNION、UNION ALL
- 常量视图
- 视图的数据源来自一个不能更新的视图
- SELECT中包含子查询
- 视图中有连接(JOIN)
- WHERE子句的子查询引用了FROM子句中的表
视图的本质就是把复杂SQL的持久化,然后方便反复使用。如果一个视图上面一个都没用到……我觉得也没必要创建视图了,所以大部分的视图可以当做是不可以修改的。
#检索视图的数据
SELECT * FROM [视图名]
#插入视图的数据
INSERT INTO [视图名](列名,列名) VALUES(值,值)
#修改视图的数据
UPDATE [视图名] SET [字段名] =[值]
#删除视图的数据
DELETE FROM [视图名]