MySQL学习代码
MySQL学习代码
SQL
全称 Structured Query Language, 结构化查询语言。操作关系型数据库的编程语言,定义了一套操作关系型数据库统一标准。
SQL通用语法
在学习具体的SQL语句之前,先来了解一下SQL语言的通用语法。
- SQL语句可以单行或多行书写,以分号结尾。
- SQL语句可以使用空格/缩进来增强语句的可读性。
- MySQL数据库的SQL语句不区分大小写,关键字建议使用大写。
- 注释:
单行注释:-- 注释内容 或 # 注释内容
多行注释:/** 注释内容* */
SQL分类
SQL 语句,根据其功能,主要分为四类:DDL、DML、DQL、DCL 。
分类 | 全称 | 说明 |
---|---|---|
DDL | Data Definition Language | 数据定义语言,用来定义数据库对象(数据库,表,字段) |
DML | Data Manipulation Language | 数据操作语言,用来对数据库表中的数据进行增删改 |
DQL | Data Query Language | 数据查询语言,用来查询数据库中表的记录 |
DCL | Data Control Language | 数据控制语言,用来创建数据库用户、控制数据库的访问权限 |
MySQL数据库基本操作—DDL
DDL:(Data Definition Language),数据定义语言,该语言部分包括以下内容:
- 对数据库的常用操作
- 对表结构的常用操作
- 修改表结构
数据库操作
1 | -- 查看所有的数据库(结尾一定要加英文[;],表示语句结束) |
表创建—格式
创建表是构建一张空表,指定这个表的名字,这个表有几列,每一列叫什么名字,以及每一列存储的数据类型。
1 | -- 创建表格式 |
数据类型—数值类型(数字类型)
1、数据类型
数据类型是指在创建表的时候为表中字段指定数据类型,只有数据符合类型要求才能存储起来,使用数据类型的原则是够用就行,尽量使用取值范围小的,而不用大的,这样可以更多的节省存储空间.
- 数值类型
数据类型—字符串类型
数据类型—日期和时间类型
还有 null 类型
- 没有值,未知
- 不要使用NULL值进行计算
数据库的字段属性
UnSigned
- 没有值,未知
- 不要使用NULL值进行计算
ZEROFILL
- 0填充的
- 不足位数的用0来填充 , 如int(3),5则为005
Auto_InCrement
- 通常理解为自增,自动在上一条记录的基础上默认+1
- 通常用来设计唯一的主键,必须是整数类型
- 可定义起始值和步长
- 当前表设置步长(AUTO_INCREMENT=100) : 只影响当前表
- SET @@auto_increment_increment=5 ; 影响所有使用自增的表(全局)
NULL 和 NOT NULL
- 默认为NULL , 即没有插入该列的数值
- 如果设置为NOT NULL , 则该列必须有值
DEFAULT
- 默认的
- 用于设置默认值
- 例如,性别字段,默认为"男" , 否则为 “女” ; 若无指定该列的值 , 则默认值为"男"的值
1 | -- 例子:执行 desc 表名; 后会出现以下结果 |
表的其他操作
1 | -- 查看当前数据库的所有表名称 |
修改表结构
修改表添加列(字段)
1 | -- 为表添加新列(字段) |
修改列名和类型
1 | -- 语法格式 |
修改表删除列
1 | -- 语法格式 |
修改表名
1 | -- 语法格式 |
MySQL数据库基本操作—DML
DML基本介绍
DML是指数据操作语言,英文全称是Data Manipulation Language,用来对数据库中表的数据记录进行更新(增删改)。
关键字:
- 插入insert
- 删除delete
- 更新update
数据插入
1 | -- 语法格式 |
数据修改
1 | -- 语法格式 |
数据删除
1 | -- 语法格式(delete 不加条件会清空该表所有数据) |
MySQL约束
简介
概念:
约束英文:constraint
约束实际上就是表中数据的限制条件。
作用
表在设计的时候加入约束的目的就是为了保证表中的记录完整性和有效性,比如用户表有些列的值(手机号)不能为空,有些列的值(身份证号)不能重复。
分类
- 主键约束(primary key) PK
- 自增长约束(auto_increment)
- 非空约束(not null)
- 唯一性约束(unique)
- 默认约束(default)
- 零填充约束(zerofill)
- 外键约束(foreign key) FK
- 检查约束(8.0.16版本之后) (check)
主键约束*
概念:
- MySQL主键约束是一个列或者多个列的组合,其值能唯一地标识表中的每一行,方便在RDBMS中尽快的找到某一行。
- 主键约束相当于唯一约束+非空约束的组合,主键约束列不允许重复,也不允许出现空值。
- 每个表最多只允许一个主键。
- 主键约束的关键字是:primary key
- 当创建主键的约束时,系统默认会在所在的列和列组合上建立对应的唯一索引。
操作
- 添加单列主键
创建单列主键有两种方式,一种是在定义字段的同时指定主键,一种是定义完字段之后指定主键。
1 | -- 方式1——语法: |
- 添加多列联合主键
所谓的联合主键,就是这个主键是由一张表中多个字段组成的。
注意:
1. 当主键是由多个字段组成时,不能直接在字段名后面声明主键约束。 2. 一张表只能有一个主键,联合主键也是一个主键。 3. 联合主键各列不能为空。
1 | -- 语法: |
通过修改表结构添加主键
主键约束不仅可以在创建表的同时创建,也可以在修改表时添加。
1 | -- 语法: |
- 删除主键约束
一个表中不需要主键约束时,就需要从表中将其删除。删除主键约束的方法要比创建主键约束容易的多。
1 | -- 格式 |
自增长约束(auto_increment)
概念:
在MySQL中,当主键定义为自增长后,这个主键的值就不再需要用户输入数据了,而由数据库系统根据定义自动赋值。每增加一条记录,主键会自动以相同的步长进行增长。
通过给字段添加 auto_increment 属性来实现主键自增长。
一般搭配主键使用,提高健壮性。
1 | -- 语法 |
特点:
默认情况下,auto_increment的初始值是 1,每新增一条记录,字段值自动加 1。
一个表中只能有一个字段使用 auto_increment约束,且该字段必须有唯一索引,以避免序号重复(即为主键或主键的一部分)。
auto_increment约束的字段必须具备 NOT NULL 属性。
auto_increment约束的字段只能是整数类型(TINYINT、SMALLINT、INT、BIGINT )等。
auto_increment约束字段的最大值受该字段的数据类型约束,如果达到上限,auto_increment就会失效。
指定自增字段初始值
- 如果第一条记录设置了该字段的初始值,那么新增加的记录就从这个初始值开始自增。例如,如果表中插入的第一条记录的id值设置为5,那么再插入记录时,id值就会从5开始往上增加。
1 | -- 方式1,创建表时指定 |
注意:delete 和 truncate 在删除后自增列的变化:
- delete数据之后自动增长从断点开始
- truncate数据之后自动增长从默认起始值开始
1 | -- 格式 |
非空约束(not null)
概念
MySQL非空约束(not null)指字段的值不能为空。对于使用了非空约束的字段,如果用户在添加数据时没有指定值,数据库系统就会报错。
1 | -- 语法: |
唯一约束(unique)
概念
唯一约束(Unique), 是指所有记录中字段的值不能重复出现。例如,为 id 字段加上唯一性约束后,每条记录的 id 值都是唯一的,不能出现重复的情况,但可以为NULL,并且可以有多个NULL。
1 | -- 语法: |
默认约束(default)
概念
MySQL默认值约束用来指定某列的默认值。
1 | -- 语法: |
零填充约束(zerofill)
概念
- 插入数据时,当该字段的值的长度小于定义的长度时,会在该值的前面补上相应的0;
- zerofill 默认为 int(10);
- 当使用 zerofill 时,默认会自动加 unsigned(无符号)属性,使用 unsigned 属性后,数值范围时原值的2倍,例如,有符号为 -128~+127,无符号为 0~256.
操作
1 | -- 语法 |
MySQL数据库基本操作—DQL
基本介绍
概念
- 数据库管理系统一个重要功能就是数据查询,数据查询不应只是简单返回数据库中存储的数据,还应该根据需要对数据进行筛选以及确定数据以什么样的格式显示。
- MySQL提供了功能强大、灵活的语句来实现这些操作。
- MySQL数据库使用select语句来查询数据。
语法
1 | -- 格式 |
我们在讲解这部分内容的时候,会将上面的完整语法进行拆分,分为以下几个部分:
- 基本查询(不带任何条件)
- 条件查询(WHERE)
- 聚合函数(count、max、min、avg、sum)
- 分组查询(group by)
- 排序查询(order by)
- 分页查询(limit)
基本查询—数据准备
以下是一个基础例子:
-
创建数据库和表(商品表):
1
2
3
4
5
6
7
8
9
10
11
12-- 创建数据库
create database if not exists mydb2;
use mydb2;
-- 创建商品表:
create table product (
pid int primary key auto_increment, -- 商品编号
pname varchar(20) not null, -- 商品名称
price double, -- 商品价格
category_id varchar(20) -- 商品所属分类
); -
添加数据:
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-- 电器类(c001):
insert into product values(null,'海尔洗衣机',5000,'c001');
insert into product values(null,'美的冰箱',3000,'c001');
insert into product values(null,'格力空调',5000,'c001');
insert into product values(null,'九阳电饭煲',5000,'c001');
-- 服装类(c002):
insert into product values(null,'啄木鸟衬衣',300,'c002');
insert into product values(null,'恒源祥西裤',800,'c002');
insert into product values(null,'花花公子夹克',440,'c002');
insert into product values(null,'劲霸休闲裤',266,'c002');
insert into product values(null,'海澜之家卫衣',180,'c002');
insert into product values(null,'杰克琼斯运动裤',430,'c002');
-- 护肤品类(c003):
insert into product values(null,'兰蔻面霜',300,'c003');
insert into product values(null,'雅诗兰黛精华水',200,'c003');
insert into product values(null,'香奈儿香水',350,'c003');
insert into product values(null,'SK-II神仙水',350,'c003');
insert into product values(null,'资生堂粉底液',180,'c003');
-- 食品类(c004):
insert into product values(null,'老北京方便面',56,'c004');
insert into product values(null,'良品铺子海带丝',17,'c004');
insert into product values(null,'三只松鼠坚果',88,'c004');
基本查询—简单查询
1 | -- 1.查询所有的商品 |
基本查询—运算符
简介
数据库中的表结构确立后,表中的数据代表的意义就已经确定。通过MySQL运算符进行运算,就可以获取到表结构以外的另一种数据。
例如,学生表中存在一个birth字段,这个字段表示学生的出 年份。 运 MySQL的算术运算符用当前的年份减学生出生的年份,那么得到的就是这个学生的实际年龄数据。
MySQL支持4种运算符
- 算术运算符
- 比较运算符
- 逻辑运算符
- 位运算符
算术运算符
算术运算符 | 说明 |
---|---|
+ | 加法运算 |
- | 减法运算 |
* | 乘法运算 |
/ 或 DIV | 除法运算,返回商 |
% 或 MOD | 求余运算,返回余数 |
比较运算符
比较运算符 | 说明 |
---|---|
= | 等于 |
< 和 <= | 小于和小于等于 |
> 和 >= | 大于和大于等于 |
<=> | 完全的等于,两个操作码均为NULL时,其所得值为1;而当一个操作码为NULL时,其所得值为0 |
<> 或 != | 不等于 |
IS NULL 或 ISNULL | 判断一个值是否为NULL |
IS NOT NULL | 判断一个值是否不为NULL |
LEAST | 当有两个或多个参数时,返回最小值 |
GREATEST | 当有两个或多个参数时,返回最大值 |
BETWEEN AND | 判断一个值是否落在两个值之间 |
IN | 判断一个值是IN列表中的任意一个值 |
NOT IN | 判断一个值不是IN列表中的任意一个值 |
LIKE | 通配符匹配(包括 % 和 _ ,%表示多个匹配,_ 表示单个匹配) |
REGEXP | 正则表达式匹配 |
逻辑运算符
逻辑运算符 | 说明 |
---|---|
NOT 或者 ! | 逻辑非 |
AND 或者 && | 逻辑与 |
OR 或者 || | 逻辑或 |
XOR | 逻辑异或 |
位运算符
位运算符 | 说明 |
---|---|
! | 按位或 |
& | 按位与 |
^ | 按位异或 |
<< | 按位左移 |
>> | 按位右移 |
~ | 按位取反,反转所有比特 |
位运算符是在二进制数上进行计算的运算符。位运算会先将操作数变成二进制数,进行位运算。然后再将计算结果从二进制数变回十进制数。
运算符操作
算术运算符
1 | use mydb2; |
比较运算符
1 | -- 更新pid为18的category_id为null |
位运算符(了解)
位运算符是在二进制数上进行计算的运算符。位运算会先将操作数变成二进制数,进行位运算。然后再将计算结果从二进制数变回十进制数。
1 | select 3 & 5; -- 位与 |
基本查询—排序查询
介绍
如果我们需要对读取的数据进行排序,我们就可以使用MySQL的 order by 子句来设定你想按哪个字段哪种方式来进行排序,再返回搜索结果。
1 | -- 语法格式: |
特点
- asc代表升序,desc代表降序,如果不写默认升序;
- order by用于子句中可以支持单个字段,多个字段,表达式,函数,别名;
- order by子句,放在查询语句的最后面。LIMIT子句除外。
操作
1 | -- 1.使用价格排序(降序) |
基本查询—聚合查询
简介
之前我们做的查询都是横向查询,它们都是根据条件一行一行的进行判断,而使用聚合函数查询是纵向查询,它是对一列的值进行计算,然后返回一个单一的值;另外聚合函数会忽略空值。
聚合函数 | 作用 |
---|---|
count() | 统计指定列不为NULL的记录行数; |
sum() | 计算指定列的数值和,如果指定列类型不是数值类型,那么计算结果为0; |
max() | 计算指定列的最大值,如果指定列是字符串类型,那么使用字符串排序运算; |
min() | 计算指定列的最小值,如果指定列是字符串类型,那么使用字符串排序运算; |
avg() | 计算指定列的平均值,如果指定列类型不是数值类型,那么计算结果为0 |
操作
1 | -- 1 查询商品的总条数 |
NULL值的处理
介绍
count函数对null值的处理:
如果count函数的参数为星号(*),则统计所有记录的个数。而如果参数为某字段,不统计含null值的记录个数。sum和avg函数对null值的处理:
这两个函数忽略null值的存在,就好像该条记录不存在一样。
max和min函数对null值的处理:
max和min两个函数同样忽略null值的存在。
操作
1 | -- 创建表 |
基本查询—分组查询—group by
简介
分组查询是指使用group by字句对查询信息进行分组。
1 | -- 格式: |
如果要进行分组的话,则select子句之后,只能出现分组的字段和统计函数,其他的字段不能出现;
分组之后的条件筛选—having
- 分组之后对统计结果进行筛选的话必须使用having,不能使用where;
- where子句用来筛选FROM子句中指定的操作所产生的行;
- group by 子句用来分组where子句的输出;
- having 子句用来从分组的结果中筛选行。
1 | -- 格式 |
基本查询—分页查询—limit
简介
分页查询在项目开发中常见,由于数据量很大,显示屏长度有限,因此对数据需要采取分页显示方式。例如数据共有30条,每页显示5条,第一页显示1-5条,第二页显示6-10条。
格式
1 | -- 方式1——显示前n条 |
操作
1 | -- 查询product表的前5条记录 |
基本查询—INSERT INTO SELECT语句
简介
将一张表的数据导入到另一张表中,可以使用INSERT INTO SELECT语句 。
格式
1 | insert into Table2(field1, field2) select value1, value2,… from Table1; |
操作
1 | -- 实例 |
SELECT INTO FROM语句
简介
将一张表的数据导入到另一张表中,有两种选择 SELECT INTO 和 INSERT INTO SELECT 。
格式
1 | select value1, value2 into Table2 from Table1; |
注意: 要求目标表Table2不存在,因为在插入时会自动创建表Table2,并将Table1中指定字段数据复制到Table2中。
操作
1 | select pname,price into product3 from product; |
练习1
1 | -- 选择数据库 |
练习2
1 | -- 选择mydb2数据库 |
正则表达式
介绍
正则表达式(regular expression)描述了一种字符串匹配的规则,正则表达式本身就是一个字符串,使用这个字符串来描述、用来定义匹配规则,匹配一系列符合某个句法规则的字符串。在开发中,正则表达式通常被用来检索、替换那些符合某个规则的文本。
MySQL通过REGEXP关键字支持正则表达式进行字符串匹配。
格式
模式 | 描述 |
---|---|
^ | 匹配输入字符串的开始位置。 |
$ | 匹配输入字符串的结束位置。 |
. | 匹配除"\n"之外的任何某个字符。 |
[…] | 字符集合。匹配所包含的任意一个字符。例如,'[abc]‘可以匹配"plain"中的’a’。 |
[^…] | 负值字符集合。匹配未包含的任意字符。例如,'[^abc]‘可以匹配"plain"中的’p’。 |
p1|p2|p3 | 匹配p1或p2或p3。例如,‘z|food’能匹配"z"或"food"。’(z|f)ood’则匹配"zood"或"food"。 |
* | 匹配前面的子表达式零次或多次。例如,"zo*“能匹配"z"以及"zoo”。 * 等价于{0,}。 |
+ | 匹配前面的子表达式一次或多次。例如,“zo+“能匹配"zo"以及"zoo”,但不能匹配"z”。+ 等价于 {1,}。 |
{n} | n 是一个非负整数。匹配确定的 n 次。例如,‘o{2}’ 不能匹配 “Bob” 中的 ‘o’,但是能匹配 “food” 中的两个 o。 |
{n,m} | m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。 |
正则表达式匹配查询
操作上
1 | -- ^ 在字符串开始处进行匹配 |
操作下
1 | -- a? 匹配0个或者1个a |
多表操作
介绍
实际开发中,一个项目通常需要很多张表才能完成。例如:一个商城项目就需要分类表(category)、商品表(products)、订单表(orders)等多张表。且这些表的数据之间存在一定的关系,接下来我们将在单表的基础上,一起学习多表方面的知识。
多表关系
MySQL多表之间的关系可以概括为:一对一、一对多/多对一关系,多对多
一对一关系
一个学生只有一张身份证;一张身份证只能对应一学生。
在任一表中添加唯一外键,指向另一方主键,确保一对一关系。
一般一对一关系很少见,遇到一对一关系的表最好是合并表。
一对多/多对一关系
部门和员工:
分析:一个部门有多个员工,一个员工只能对应一个部门;
实现原则:在多的一方建立外键,指向一的一方的主键。
多对多关系
学生和课程:
分析:一个学生可以选择很多门课程,一个课程也可以被很多学生选择;
原则:多对多关系实现需要借助第三张中间表。中间表至少包含两个字段,将多对多的关系,拆成一对多的关系,中间表至少要有两个外键,这两个外键分别指向原来的那两张表的主键。
注:多对多的关系需要一个中间表作为桥梁
外键约束—概念
介绍
MySQL 外键约束(FOREIGN KEY)是表的一个特殊字段,经常与主键约束一起使用。对于两个具有关联关系的表而言,相关联字段中主键所在的表就是主表(父表),外键所在的表就是从表(子表)。
外键用来建立主表与从表的关联关系,为两个表的数据建立连接,约束两个表中数据的一致性和完整性。比如,一个水果摊,只有苹果、桃子、李子、西瓜等 4 种水果,那么,你来到水果摊要买水果就只能选择苹果、桃子、李子和西瓜,其它的水果都是不能购买的。
特点
定义一个外键时,需要遵守下列规则:
主表必须已经存在于数据库中,或者是当前正在创建的表。
必须为主表定义主键。
主键不能包含空值,但允许在外键中出现空值。也就是说,只要外键的每个非空值出现在指定的主键中,这 个外键的内容就是正确的。
在主表的表名后面指定列名或列名的组合。这个列或列的组合必须是主表的主键或候选键。
外键中列的数目必须和主表的主键中列的数目相同。
外键中列的数据类型必须和主表主键中对应列的数据类型相同。
外键约束—一对多关系
操作-创建外键约束
方式1-在创建表时设置外键约束
在 create table 语句中,通过 foreign key
关键字来指定外键,具体的语法格式如下:
1 | [constraint <外键名>] foreign key 字段名 [,字段名2,…] references <主表名> 主键列1 [,主键列2,…]; |
实现:
1 | create database mydb3; |
方式2-在创建表时设置外键约束
外键约束也可以在修改表时添加,但是添加外键约束的前提是:从表中外键列中的数据必须与主表中主键列中的数据一致或者是没有数据。
1 | alter table <数据表名> add constraint <外键名> foreign key(<列名>) references <主表名> (<列名>); |
实现:
1 | -- 创建部门表 |
操作-在外键约束下的数据操作
验证外键约束的作用
1、数据插入
1 | -- 1、添加主表数据 |
2、删除数据
1 | -- 3、删除数据 |
操作-删除外键约束
当一个表中不需要外键约束时,就需要从表中将其删除。外键一旦删除,就会解除主表和从表间的关联关系
格式:
1 | alter table <表名> drop foreign key <外键约束名>; |
实现:
1 | alter table emp2 drop foreign key dept_id_fk; |
外键约束-多对多关系
介绍
在多对多关系中,A表的一行对应B的多行,B表的一行对应A表的多行,我们要新增加一个中间表,来建立多对多关系。
操作
1 | -- 选择mydb3数据库 |
注意:修改和删除时,中间从表可以随便删除和修改,但是两边的主表受从表依赖的数据不能删除或者修改。
多表联合查询
介绍
多表查询就是同时查询两个或两个以上的表,因为有的时候用户在查看数据的时候,需要显示的数据来自多张表。
多表查询有以下分类:
1 | 交叉连接查询 [产生笛卡尔积,了解] |
准备查询数据
接下来准备多表查询需要数据,注意,外键约束对多表查询并无影响。
1 | use mydb3; |
多表联合查询—交叉连接查询
- 交叉连接查询返回被连接的两个表所有数据行的笛卡尔积
- 笛卡尔积可以理解为一张表的每一行去和另外一张表的任意一行进行匹配
- 假如A表有m行数据,B表有n行数据,则返回m*n行数据
- 笛卡尔积会产生很多冗余的数据,后期的其他查询可以在该集合的基础上进行条件筛选
格式:
1 | select * from 表1,表2,表3….; |
实现:
1 | -- 交叉连接查询 |
结果:
多表联合查询—内连接查询
内连接查询求多张表的交集
格式
1 | 隐式内连接(SQL92标准):select * from A,B where 条件; |
操作
1 | -- 查询每个部门的所属员工 |
外连接查询
- 外连接分为左外连接(left outer join)、右外连接(right outer join),满外连接(full outer join)。
- 注意:oracle里面有full join,可是在mysql对full join支持的不好。我们可以使用union来达到目的。
格式
1 | 左外连接:left outer join |
操作
1 | -- 外连接查询 |
子查询
介绍
子查询就是指的在一个完整的查询语句之中,嵌套若干个不同功能的小查询,从而一起完成复杂查询的一种编写形式,通俗一点就是包含select嵌套的查询。
特点
子查询可以返回的数据类型一共分为四种:
- 单行单列:返回的是一个具体列的内容,可以理解为一个单值数据;
- 单行多列:返回一行数据中多个列的内容;
- 多行单列:返回多行记录之中同一列的内容,相当于给出了一个操作范围;
- 多行多列:查询返回的结果是一张临时表
操作
1 | -- 查询年龄最大的员工信息,显示信息包含员工号、员工名字,员工年龄 |
子查询关键字
介绍
在子查询中,有一些常用的逻辑关键字,这些关键字可以给我们提供更丰富的查询功能,主要关键字如下:
- ALL关键字
- ANY关键字
- SOME关键字
- IN关键字
- EXISTS关键字
子查询关键字—ALL
格式
1 | select …from …where c > all(查询语句) |
特点
- ALL: 与子查询返回的所有值比较为true则返回true
- ALL可以与=、>、>=、<、<=、<>结合是来使用,分别表示等于、大于、大于等于、小于、小于等于、不等于其中的其中的所有数据。
- ALL表示指定列中的值必须要大于子查询集的每一个值,即必须要大于子查询集的最大值;如果是小于号即小于子查询集的最小值。同理可以推出其它的比较运算符的情况。
操作
1 | -- 1.查询年龄大于‘1003’部门所有年龄的员工信息 |
子查询关键字-ANY和SOME
格式
1 | select …from …where c > any(查询语句) |
特点
- ANY:与子查询返回的任何值比较为true 则返回true
- ANY可以与=、>、>=、<、<=、<>结合是来使用,分别表示等于、大于、大于等于、小于、小于等于、不等于其中的其中的任何一个数据。
- 表示制定列中的值要大于子查询中的任意一个值,即必须要大于子查询集中的最小值。同理可以推出其它的比较运算符的情况。
- SOME和ANY的作用一样,SOME可以理解为ANY的别名
操作
1 | -- 查询年龄大于‘1003’部门任意一个员工年龄的员工信息 |
子查询关键字-IN
格式
1 | select …from …where c in(查询语句) |
特点
- IN关键字,用于判断某个记录的值,是否在指定的集合中
- 在IN关键字前边加上not可以将条件反过来
操作
1 | -- 查询研发部和销售部的员工信息,包含员工号、员工名字 |
子查询关键字-EXISTS
格式
1 | select …from …where exists(查询语句) |
特点
- 该子查询如果“有数据结果”(至少返回一行数据), 则该EXISTS() 的结果为“true”,外层查询执行
- 该子查询如果“没有数据结果”(没有任何数据返回),则该EXISTS()的结果为“false”,外层查询不执行
- EXISTS后面的子查询不返回任何实际数据,只返回真或假,当返回真时 where条件成立
- 注意,EXISTS关键字,比IN关键字的运算效率高,因此,在实际开发中,特别是大数据量时,推荐使用EXISTS关键字
- 有exists的时候是从外向内查询(在exists中判断),而其他的都是从内向外查询
操作
1 | -- 查询公司是否有大于60岁的员工,有则输出 |
自关联查询
概念
MySQL有时在信息查询时需要进行对表自身进行关联查询,即一张表自己和自己关联,一张表当成多张表来用。注意自关联时表必须给表起别名。
格式
1 | select 字段列表 from 表1 a , 表1 b where 条件; |
操作
1 | -- 创建表,并建立自关联约束 |
练习
1 | -- 创建test1数据库 |
MySQL函数
基本介绍
概述
在MySQL中,为了提高代码重用性和隐藏实现细节,MySQL提供了很多函数。函数可以理解为别人封装好的模板代码。
分类
在MySQL中,函数非常多,主要可以分为以下几类:
- 聚合函数
- 数学函数
- 字符串函数
- 日期函数
- 控制流函数
- 窗口函数
聚合函数
概述
- 在MySQL中,聚合函数主要由:count, sum, min, max, avg, 这些聚合函数我们之前都学过,不再重复。这里我们学习另外一个函数:
group_concat()
,该函数用户实现行的合并。 group_concat()
函数首先根据group by指定的列进行分组,并且用分隔符分隔,将同一个分组中的值连接起来,返回一个字符串结果。
格式
1 | group_concat([distinct] 字段名 [order by 排序字段 asc/desc] [separator '分隔符']) |
说明:
(1)使用distinct可以排除重复值;
(2)如果需要对结果中的值进行排序,可以使用order by子句;
(3)separator是一个字符串值,默认为逗号。
操作
1 | -- 创建并选择mydb4 |
1 | -- 将所有员工的名字合并成一行 |
1 | -- 指定分隔符合并 |
1 | -- 指定排序方式和分隔符 |
数学函数
函数名
由于表格行数有限,也为了方便查看,以下分为三张表来展示(加粗代表常用):
函数名 | 描述 | 实例 |
---|---|---|
ABS(x) | 返回 x 的绝对值 | 返回 -1 的绝对值:SELECT ABS(-1) – 返回1 |
CEIL(x) | 返回大于或等于 x 的最小整数(向上取整) | SELECT CEIL(1.5) – 返回2 |
FLOOR(x) | 返回小于或等于 x 的最大整数(向下取整) | 小于或等于 1.5 的整数:SELECT FLOOR(1.5) – 返回1 |
GREATEST(expr1, expr2, expr3, …) | 返回列表中的最大值 | 返回以下数字列表中的最大值:SELECT GREATEST(3, 12, 34, 8, 25); – 34返回以下字符串列表中的最大值:SELECT GREATEST(“Google”, “Runoob”, “Apple”); – Runoob |
LEAST(expr1, expr2, expr3, …) | 返回列表中的最小值 | 返回以下数字列表中的最小值:SELECT LEAST(3, 12, 34, 8, 25); – 3返回以下字符串列表中的最小值:SELECT LEAST(“Google”, “Runoob”, “Apple”); – Apple |
函数名 | 描述 | 实例 |
---|---|---|
MAX(expression) | 返回字段 expression 中的最大值 | 返回数据表 Products 中字段 Price 的最大值:SELECT MAX(Price) AS LargestPrice FROM Products; |
MIN(expression) | 返回字段 expression 中的最小值 | 返回数据表 Products 中字段 Price 的最小值:SELECT MIN(Price) AS MinPrice FROM Products; |
MOD(x,y) | 返回 x 除以 y 以后的余数 | 5 除于 2 的余数:SELECT MOD(5,2) – 1 |
PI() | 返回圆周率(3.141593) | SELECT PI() --3.141593 |
POW(x,y) | 返回 x 的 y 次方 | 2 的 3 次方:SELECT POW(2,3) – 8 |
函数名 | 描述 | 实例 |
---|---|---|
RAND() | 返回 0 到 1 的随机数 | SELECT RAND() --0.93099315644334 |
ROUND(x) | 返回离 x 最近的整数(遵循四舍五入) | SELECT ROUND(1.23456) --1 |
ROUND(x,y) | 返回指定位数的小数(遵循四舍五入) | SELECT ROUND(1.23456,3) –1.235 |
TRUNCATE(x,y) | 返回数值 x 保留到小数点后 y 位的值(与 ROUND 最大的区别是不会进行四舍五入) | SELECT TRUNCATE(1.23456,3) – 1.234 |
操作
1 | -- 案例:通过数据库的函数,生成一个六位数的随机验证码。 |
字符串函数
字符串等的位置:从1开始;索引:从0开始。两者都是描述位置的,但是计数起点不同。
函数名
函数 | 描述 | 实例 |
---|---|---|
CHAR_LENGTH(s) | 返回字符串 s 的字符数 | 返回字符串 RUNOOB 的字符数SELECT CHAR_LENGTH(“RUNOOB”) AS LengthOfString; |
LENGTH(s) | 返回字符串 s 的字节数 | SELECT LENGTH(“明天”) AS LengthOfString; – 6(utf-8 一个汉字为3个字节) |
CHARACTER_LENGTH(s) | 返回字符串 s 的字符数 | 返回字符串 RUNOOB 的字符数SELECT CHARACTER_LENGTH(“RUNOOB”) AS LengthOfString; |
CONCAT(s1,s2…sn) | 字符串 s1,s2 等多个字符串合并为一个字符串 | 合并多个字符串SELECT CONCAT("SQL ", "Runoob ", "Gooogle ", “Facebook”) AS ConcatenatedString; |
CONCAT_WS(x, s1,s2…sn) | 同 CONCAT(s1,s2,…) 函数,但是每个字符串之间要加上 x,x 可以是分隔符 | 合并多个字符串,并添加分隔符:SELECT CONCAT_WS(“-”, “SQL”, “Tutorial”, “is”, “fun!”)AS ConcatenatedString; |
FIELD(s,s1,s2…) | 返回第一个字符串 s 在字符串列表(s1,s2…)中的位置 | 返回字符串 c 在列表值中的位置:SELECT FIELD(“c”, “a”, “b”, “c”, “d”, “e”,“c”); 后面重复的’c’就不会输出位置,只能输出第一个查到的‘c’ |
函数 | 描述 | 实例 |
---|---|---|
LTRIM(s) | 去掉字符串 s 开始处的空格 | 去掉字符串 RUNOOB开始处的空格:SELECT LTRIM(" RUNOOB") AS LeftTrimmedString;-- RUNOOB |
RTRIM(s) | 去掉字符串 s 结尾处的空格 | 去掉字符串 RUNOOB结尾处的空格:SELECT RTRIM(" RUNOOB ") AS LeftTrimmedString;-- RUNOOB |
MID(s,n,len) | 从字符串 s 的 n 位置截取长度为 len 的子字符串,同 SUBSTRING(s,n,len) | 从字符串 RUNOOB 中的第 2 个位置截取 3个 字符:SELECT MID(“RUNOOB”, 2, 3) AS ExtractString; – UNO |
POSITION(s1 IN s) | 从字符串 s 中获取 s1 的开始位置 | 返回字符串 abc 中 b 的位置:SELECT POSITION(‘b’ in ‘abc’) – 2 |
REPLACE(s,s1,s2) | 将字符串 s2 替代字符串 s 中的字符串 s1 | 将字符串 abc 中的字符 a 替换为字符 x:SELECT REPLACE(‘abca’,‘a’,‘x’) --xbcx |
REVERSE(s) | 将字符串s的顺序反过来 | 将字符串 abc 的顺序反过来:SELECT REVERSE(‘abc’) – cba |
函数 | 描述 | 实例 |
---|---|---|
LEFT(s,n) | 返回字符串 s 的前 n 个字符 | 返回字符串 runoob 的前两个字符:SELECT left(‘runoob’,2) – ru |
RIGHT(s,n) | 返回字符串 s 的后 n 个字符 | 返回字符串 runoob 的后两个字符:SELECT RIGHT(‘runoob’,2) – ob |
STRCMP(s1,s2) | 比较字符串 s1 和 s2,如果 s1 与 s2 相等返回 0 ,如果 s1>s2 返回 1,如果 s1<s2 返回 -1 | 比较字符串:SELECT STRCMP(“runoob”, “runoob”); – 0 |
SUBSTR(s, start, length) | 从字符串 s 的 start 位置截取长度为 length 的子字符串 | 从字符串 RUNOOB 中的第 2 个位置截取 3个 字符:SELECT SUBSTR(“RUNOOB”, 2, 3) AS ExtractString; – UNO |
SUBSTRING(s, start, length) | 从字符串 s 的 start 位置截取长度为 length 的子字符串 | 从字符串 RUNOOB 中的第 2 个位置截取 3个 字符:SELECT SUBSTRING(“RUNOOB”, 2, 3) AS ExtractString; – UNO |
函数 | 描述 | 实例 |
---|---|---|
TRIM(s) | 去掉字符串 s 开始和结尾处的空格 | 去掉字符串 RUNOOB 的首尾空格:SELECT TRIM(’ RUNOOB ') AS TrimmedString; |
UCASE(s) | 将字符串转换为大写 | 将字符串 runoob 转换为大写:SELECT UCASE(“runoob”); – RUNOOB |
UPPER(s) | 将字符串转换为大写 | 将字符串 runoob 转换为大写:SELECT UPPER(“runoob”); – RUNOOB |
LCASE(s) | 将字符串 s 的所有字母变成小写字母 | 字符串 RUNOOB 转换为小写:SELECT LCASE(‘RUNOOB’) – runoob |
LOWER(s) | 将字符串 s 的所有字母变成小写字母 | 字符串 RUNOOB 转换为小写:SELECT LOWER(‘RUNOOB’) – runoob |
LPAD(str,n,pad) | 左填充,用字符串pad对str的左边进行填充,达到n个字符串长度 | 左填充:select lpad(‘01’,5,‘-’); |
RPAD(str,n,pad) | 右填充,用字符串pad对str的右边进行填充,达到n个字符串长度 | 右填充:select rpad(‘01’,5,‘-’); |
操作
1 | -- 案例:由于业务需求变更,企业员工的工号,统一为5位数,目前不足5位数的全部在前面补0,比如:1号员工的工号应该为00001 |
日期函数
函数名
函数名 | 描述 | 实例 |
---|---|---|
UNIX_TIMESTAMP() | 返回从1970-01-01 00:00:00到当前毫秒值(时间戳) | select UNIX_TIMESTAMP() -> 1632729059 |
UNIX_TIMESTAMP(DATE_STRING) | 将制定日期转为毫秒值时间戳 | SELECT UNIX_TIMESTAMP(‘2011-12-07 13:01:03’); |
FROM_UNIXTIME(BIGINT UNIXTIME[, STRING FORMAT]) | 将毫秒值时间戳转为指定格式日期 | SELECT FROM_UNIXTIME(1598079966,‘%Y-%m-%d %H:%i:%s’); (1598079966,‘%Y-%m-%d %H:%i:%s’); -> 2020-08-22 15-06-06 |
CURDATE() | 返回当前日期 | SELECT CURDATE();-> 2018-09-19 |
CURRENT_DATE() | 返回当前日期 | SELECT CURRENT_DATE();-> 2018-09-19 |
函数名 | 描述 | 实例 |
---|---|---|
CURRENT_TIME | 返回当前时间 | SELECT CURRENT_TIME();-> 19:59:02 |
CURTIME() | 返回当前时间 | SELECT CURTIME();-> 19:59:02 |
CURRENT_TIMESTAMP() | 返回当前日期和时间 | SELECT CURRENT_TIMESTAMP()-> 2018-09-19 20:57:43 |
DATE() | 从日期或日期时间表达式中提取日期值 | SELECT DATE(“2017-06-15”); -> 2017-06-15 |
DATEDIFF(d1,d2) | 计算日期 d1->d2 之间相隔的天数 | SELECT DATEDIFF(‘2001-01-01’,‘2001-02-02’)-> -32 |
函数名 | 描述 | 实例 |
---|---|---|
TIMEDIFF(time1, time2) | 计算时间差值 | SELECT TIMEDIFF(“13:10:11”, “13:10:10”);-> 00:00:01 |
DATE_FORMAT(d,f) | 按表达式 f的要求显示日期 d | SELECT DATE_FORMAT(‘2011-11-11 11:11:11’,‘%Y-%m-%d %r’)-> 2011-11-11 11:11:11 AM |
STR_TO_DATE(string, format_mask) | 将字符串转变为日期 | SELECT STR_TO_DATE(“August 10 2017”, “%M %d %Y”);-> 2017-08-10 |
DATE_SUB(date,INTERVAL expr type) | 函数从日期减去指定的时间间隔。 | Orders 表中 OrderDate 字段减去 2 天:SELECT OrderId,DATE_SUB(OrderDate,INTERVAL 2 DAY) AS OrderPayDate FROM Orders; |
函数名 | 描述 | 实例 |
---|---|---|
ADDDATE/DATE_ADD(d,INTERVAL expr type) | 计算起始日期 d 加上一个时间段后的日期,type 值可以是: MICROSECOND SECOND MINUTE HOUR DAY WEEK MONTH QUARTER YEAR DAY_MINUTE DAY_HOUR YEAR_MONTH |
SELECT DATE_ADD(“2017-06-15”, INTERVAL 10 DAY); -> 2017-06-25 SELECT DATE_ADD(“2017-06-15 09:34:21”, INTERVAL 15 MINUTE); -> 2017-06-15 09:49:21 SELECT DATE_ADD(“2017-06-15 09:34:21”, INTERVAL -3 HOUR); ->2017-06-15 06:34:21 SELECT DATE_ADD(“2017-06-15 09:34:21”, INTERVAL -3 HOUR); ->2017-04-15 |
函数名 | 描述 | 实例 |
---|---|---|
DATE_ADD(d,INTERVAL expr type) | 计算起始日期 d 加上一个时间段后的日期,type 值可以是: SECOND_MICROSECOND MINUTE_MICROSECOND MINUTE_SECOND HOUR_MICROSECOND HOUR_SECOND HOUR_MINUTE DAY_MICROSECOND DAY_SECOND DAY_MINUTE DAY_HOUR YEAR_MONTH |
SELECT DATE_ADD(“2017-06-15”, INTERVAL 10 DAY); -> 2017-06-25 SELECT DATE_ADD(“2017-06-15 09:34:21”, INTERVAL 15 MINUTE); -> 2017-06-15 09:49:21 SELECT DATE_ADD(“2017-06-15 09:34:21”, INTERVAL -3 HOUR); ->2017-06-15 06:34:21 SELECT DATE_ADD(“2017-06-15 09:34:21”, INTERVAL -3 HOUR); ->2017-04-15 |
EXTRACT(type FROM d) | 从日期 d 中获取指定的值,type 指定返回的值。type可取值为:MICROSECOND SECOND MINUTE HOUR …… |
SELECT EXTRACT(MINUTE FROM ‘2011-11-11 11:11:11’) -> 11 |
LAST_DAY(d) | 返回给给定日期的那一月份的最后一天 | SELECT LAST_DAY(“2017-06-20”);-> 2017-06-30 |
MAKEDATE(year, day-of-year) | 基于给定参数年份 year 和所在年中的天数序号 day-of-year 返回一个日期 | SELECT MAKEDATE(2017, 3);-> 2017-01-03 |
函数名 | 描述 | 实例 |
---|---|---|
YEAR(d) | 返回年份 | SELECT YEAR(“2017-06-15”);-> 2017 |
MONTH(d) | 返回日期d中的月份值,1 到 12 | SELECT MONTH(‘2011-11-11 11:11:11’)->11 |
DAY(d) | 返回日期值 d 的日期部分 | SELECT DAY(“2017-06-15”); -> 15 |
HOUR(t) | 返回 t 中的小时值 | SELECT HOUR(‘1:2:3’)-> 1 |
MINUTE(t) | 返回 t 中的分钟值 | SELECT MINUTE(‘1:2:3’)-> 2 |
SECOND(t) | 返回 t 中的秒钟值 | SELECT SECOND(‘1:2:3’)-> 3 |
QUARTER(d) | 返回日期d是第几季节,返回 1 到 4 | SELECT QUARTER(‘2011-11-11 11:11:11’)-> 4 |
函数名 | 描述 | 实例 |
---|---|---|
MONTHNAME(d) | 返回日期当中的月份名称,如 November | SELECT MONTHNAME(‘2011-11-11 11:11:11’)-> November |
DAYNAME(d) | 返回日期 d 是星期几,如 Monday,Tuesday | SELECT DAYNAME(‘2011-11-11 11:11:11’)->Friday |
DAYOFMONTH(d) | 计算日期 d 是本月的第几天 | SELECT DAYOFMONTH(‘2011-11-11 11:11:11’)->11 |
DAYOFWEEK(d) | 日期 d 今天是星期几,1 星期日,2 星期一,以此类推 | SELECT DAYOFWEEK(‘2011-11-11 11:11:11’)->6 |
DAYOFYEAR(d) | 计算日期 d 是本年的第几天 | SELECT DAYOFYEAR(‘2011-11-11 11:11:11’)->315 |
函数名 | 描述 | 实例 |
---|---|---|
WEEK(d) | 计算日期 d 是本年的第几个星期,范围是 0 到 53 | SELECT WEEK(‘2011-11-11 11:11:11’)-> 45 |
WEEKDAY(d) | 日期 d 是星期几,0 表示星期一,1 表示星期二 | SELECT WEEKDAY(“2017-06-15”);-> 3 |
WEEKOFYEAR(d) | 计算日期 d 是本年的第几个星期,范围是 0 到 53 | SELECT WEEKOFYEAR(‘2011-11-11 11:11:11’)-> 45 |
YEARWEEK(date, mode) | 返回年份及第几周(0到53),mode 中 0 表示周天,1表示周一,以此类推 | SELECT YEARWEEK(“2017-06-15”);-> 201724 |
NOW() | 返回当前日期和时间 | SELECT NOW()-> 2018-09-19 20:57:43 |
操作
1 | -- 案例:查询所有员工的入职天数,并根据入职天数倒序排序。 |
控制流函数
if逻辑判断语句
格式 | 解释 | 案例 |
---|---|---|
IF(expr,v1,v2) | 如果表达式 expr 成立,返回结果 v1;否则,返回结果 v2。 | SELECT IF(1 > 0,‘正确’,‘错误’) ->正确 |
IFNULL(v1,v2) | 如果 v1 的值不为 NULL,则返回 v1,否则返回 v2。 | SELECT IFNULL(null,‘Hello Word’) ->Hello Word |
ISNULL(expression) | 判断表达式是否为 NULL | SELECT ISNULL(NULL); ->1 |
NULLIF(expr1, expr2) | 比较两个字符串,如果字符串 expr1 与 expr2 相等 返回 NULL,否则返回 expr1 | SELECT NULLIF(25, 25); ->null |
case when语句
格式 | 解释 | 操作 |
---|---|---|
CASE expression WHEN condition1 THEN result1 WHEN condition2 THEN result2 … WHEN conditionN THEN resultN ELSE result END |
CASE 表示函数开始,END 表示函数结束。如果 condition1 成立,则返回 result1, 如果 condition2 成立,则返回 result2,当全部不成立则返回 result,而当有一个成立之后,后面的就不执行了。 | select case 100 when 50 then ‘tom’ when 100 then ‘mary’else ‘tim’ end ; select case when 1=2 then ‘tom’ when 2=2 then ‘mary’ else’tim’ end ; |
案例
1 | -- 案例1: |
窗口函数
介绍
- MySQL 8.0 新增窗口函数 ,窗口函数又被称为开窗函数,与Oracle 窗口函数类似,属于MySQL的一大特点。
- 非聚合窗口函数是相对于聚函数来说的。聚合函数是对一组数据计算后返回单个值(即分组),非聚合函数一次只会处理一行数据。窗口聚合函数在行记录上计算某个字段的结果时,可将窗口范围内的数据输入到聚合函数中,并不改变行数。
分类
另外还有开窗聚合函数: SUM
,AVG
,MIN
,MAX
语法结构
1 | window_function ( expr ) OVER ( |
其中,window_function 是窗口函数的名称;expr 是参数,有些函数不需要参数;OVER子句包含三个选项:
- 分区(PARTITION BY):
PARTITION BY选项用于将数据行拆分成多个分区(组),它的作用类似于GROUP BY分组。如果省略了 PARTITION BY,所有的数据作为一个组进行计算
- 排序(ORDER BY):
OVER 子句中的ORDER BY选项用于指定分区内的排序方式,与 ORDER BY 子句的作用类似
- 以及窗口大小(frame_clause):
frame_clause选项用于在当前分区内指定一个计算窗口,也就是一个与当前行相关的数据子集。
序号函数
序号函数有三个:ROW_NUMBER()、RANK()、DENSE_RANK(),可以用来实现分组排序,并添加序号。
格式
1 | row_number()|rank()|dense_rank() over ( |
操作
1 | use mydb4; |
row_number()
1 | -- 对每个部门的员工按照薪资降序排序,并给出排名 |
rank()
1 | -- 对每个部门的员工按照薪资排序,并给出排名 rank |
dense_rank()
1 | -- 对每个部门的员工按照薪资排序,并给出排名 dense-rank |
1 | --求出每个部门薪资排在前三名的员工- 分组求TOPN |
1 | -- 对所有员工进行全局排序(不分组) |
开窗聚合函数- SUM,AVG,MIN,MAX
概念
在窗口中每条记录动态地应用聚合函数(SUM()、AVG()、MAX()、MIN()、COUNT()),可以动态计算在指定的窗口内的各种聚合函数值。
操作
1 | -- 开窗聚合函数 |
分布函数-(CUME_DIST)
介绍
- 用途:分组内小于、等于当前rank值的行数 / 分组内总行数
- 应用场景:查询小于等于当前薪资(salary)的比例
操作
1 | select |
分布函数-(PERCENT_RANK)
介绍
- 用途:每行按照公式(rank-1) / (rows-1)进行计算。其中,rank为RANK()函数产生的序号,rows为当前窗口的记录总行数;
- 应用场景:不常用。
操作
1 | select |
前后函数-LAG和LEAD
介绍
- 用途:返回位于当前行的前n行(LAG(expr,n))或后n行(LEAD(expr,n))的expr的值
- 应用场景:查询前1名同学的成绩和当前同学成绩的差值
操作
1 | -- lag的用法 |
LAG(expr,n)
:
LEAD(expr,n)
:
头尾函数-FIRST_VALUE和LAST_VALUE
介绍
用途:返回第一个(FIRST_VALUE(expr))或最后一个(LAST_VALUE(expr))expr的值
应用场景:截止到当前,按照日期排序查询第1个入职和最后1个入职员工的薪资
操作
1 | -- 注意, 如果不指定ORDER BY,则进行排序混乱,会出现错误的结果 |
其他函数-NTH_VALUE(expr, n)、NTILE(n)
介绍-NTH_VALUE(expr,n)
- 用途:返回窗口中第n个expr的值。expr可以是表达式,也可以是列名
- 应用场景:截止到当前薪资,显示每个员工的薪资中排名第2或者第3的薪资
操作
1 | -- 查询每个部门截止目前薪资排在第二和第三的员工信息 |
介绍-NTILE(n)
- 用途:将分区中的有序数据分为n个等级,记录等级数
- 应用场景:将每个部门员工按照入职日期分成3组
操作
1 | -- 根据入职日期将每个部门的员工分成3组 |
练习
1 | -- 取出每个部门的第一组员工 |
MySQL的视图
介绍
- 视图(view)是一个虚拟表,非真实存在,其本质是根据SQL语句获取动态的数据集,并为其命名,用户使用时只需使用视图名称即可获取结果集,并可以将其当作表来使用。(就是原表的一个映射)
- 数据库中只存放了视图的定义,而并没有存放视图中的数据。这些数据存放在原来的表中。
- 使用视图查询数据时,数据库系统会从原来的表中取出对应的数据。因此,视图中的数据是依赖于原来的表中的数据的。一旦表中的数据发生改变,显示在视图中的数据也会发生改变。
作用
- 简化代码,可以把重复使用的查询封装成视图重复使用,同时可以使复杂的查询易于理解和使用。
- 安全原因,如果一张表中有很多数据,很多信息不希望让所有人看到,此时可以使用视图视,如:社会保险基金表,可以用视图只显示姓名,地址,而不显示社会保险号和工资数等,可以对不同的用户,设定不同的视图。
视图的创建
格式
创建视图的语法为:
1 | create [or replace] [algorithm = {undefined | merge | temptable}] |
数据准备
创建 数据库mydb6_view,然后在该数据库下执行sql脚本view_data.sql 导入数据
1 | create database mydb6_view; |
操作
1 | -- 创建视图 |
修改视图
修改视图是指修改数据库中已存在的表的定义。当基本表的某些字段发生改变时,可以通过修改视图来保持视图和基本表之间一致。MySQL中通过CREATE OR REPLACE VIEW
语句来创建视图和ALTER VIEW
语句来修改视图。
格式
1 | alter view 视图名 as select语句 |
操作
1 | alter view view1_emp |
更新视图
介绍
某些视图是可更新的。也就是说,可以在UPDATE、DELETE或INSERT等语句中使用它们,以更新基表的内容。对于可更新的视图,在视图中的行和基表中的行之间必须具有一对一的关系。如果视图包含下述结构中的任何一种,那么它就是不可更新的:
- 聚合函数(SUM(), MIN(), MAX(), COUNT()等)
- DISTINCT
- GROUP BY
- ORDER BY
- HAVING
- UNION或UNION ALL
- 位于选择列表中的子查询
- JOIN
- FROM子句中的不可更新视图
- WHERE子句中的子查询,引用FROM子句中的表。
- 仅引用文字值(在该情况下,没有要更新的基本表)
视图中虽然可以更新数据,但是有很多的限制。一般情况下,最好将视图作为查询数据的虚拟表,而不要通过视图更新数据。因为,使用视图更新数据时,如果没有全面考虑在视图中更新数据的限制,就可能会造成数据更新失败。
操作
1 | -- ---------更新视图------- |
其他操作
重命名视图
1 | -- rename table 视图名 to 新视图名; |
删除视图
1 | -- drop view 视图名[,视图名…]; |
删除视图时,只能删除视图的定义,不会删除数据。
练习
1 | -- 1:查询部门平均薪水最高的部门名称 |
MySQL的存储过程
介绍
- 什么是存储过程
- MySQL 5.0 版本开始支持存储过程。
- 简单的说,存储过程就是一组SQL语句集,功能强大,可以实现一些比较复杂的逻辑功能,类似于JAVA语言中的方法;
- 存储过就是数据库 SQL 语言层面的代码封装与重用。
- 有哪些特性
- 有输入输出参数,可以声明变量,有if/else, case,while等控制语句,通过编写存储过程,可以实现复杂的逻辑功能;
- 函数的普遍特性:模块化,封装,代码复用;
- 速度快,只有首次执行需经过编译和优化步骤,后续被调用可以直接执行,省去以上步骤;
入门案例
格式
1 | delimiter 自定义结束符号 |
操作-数据准备
1 | -- 1:创建数据库和表 |
MySQL操作-变量定义
局部变量
格式
用户自定义,在begin/end块中有效
1 | 语法: 声明变量 declare var_name type [default var_value]; |
操作
1 | -- 定义局部变量 |
MySQL 中还可以使用 SELECT…INTO 语句为变量赋值。其基本语法如下:
1 | -- 格式 |
用户变量
格式
用户自定义,当前会话(连接)有效。类比java的成员变量
1 | 语法: |
操作
1 | delimiter $$ |
系统变量
介绍
- 系统变量又分为全局变量与会话变量。
- 全局变量在MYSQL启动的时候由服务器自动将它们初始化为默认值,这些默认值可以通过更改my.ini这个文件来更改。
- 会话变量在每次建立一个新的连接的时候,由MYSQL来初始化。MYSQL会将当前所有全局变量的值复制一份。来做为会话变量。
- 也就是说,如果在建立会话以后,没有手动更改过会话变量与全局变量的值,那所有这些变量的值都是一样的。
- 全局变量与会话变量的区别就在于,对全局变量的修改会影响到整个服务器,但是对会话变量的修改,只会影响到当前的会话(也就是当前的数据库连接)。
- 有些系统变量的值是可以利用语句来动态进行更改的,但是有些系统变量的值却是只读的,对于那些可以更改的系统变量,我们可以利用set语句进行更改。
系统变量-全局变量
由系统提供,在整个数据库有效。
格式
1 | 语法: |
操作
1 | -- 查看全局变量 |
系统变量-会话变量
由系统提供,当前会话(连接)有效
格式
1 | 语法: |
操作
1 | -- 查看会话变量 |
存储过程传参-in
in 表示传入的参数, 可以传入数值或者变量,即使传入变量,并不会更改变量的值,可以内部更改,仅仅作用在函数范围内。
1 | -- 封装有参数的存储过程,传入员工编号,查找员工信息 |
存储过程传参-out
out 表示从存储过程内部传值给调用者
1 | -- ---------传出参数:out--------------------------------- |
存储过程传参-inout
inout 表示从外部传入的参数经过修改后可以返回的变量,既可以使用传入变量的值也可以修改变量的值(即使函数执行完)
1 | -- 传入员工名,拼接部门号,传入薪资,求出年薪 |
存储过程传参-in,out, inout
总结
in 输入参数,意思说你的参数要传到存过过程的过程里面去,在存储过程中修改该参数的值不能被返回
out 输出参数:该值可在存储过程内部被改变,并向外输出
inout 输入输出参数,既能输入一个值又能传出来一个值)
流程控制-判断
格式
IF语句包含多个条件判断,根据结果为TRUE、FALSE执行语句,与编程语言中的if、else if、else语法类似,其语法格式如下:
1 | -- 语法 |
操作
1 | -- 输入学生的成绩,来判断成绩的级别: |
流程控制-case
CASE是另一个条件判断的语句,类似于编程语言中的switch语法
操作
1 | -- 语法一(类比java的switch): |
流程控制-循环
概述:
- 循环是一段在程序中只出现一次,但可能会连续运行多次的代码。
- 循环中的代码会运行特定的次数,或者是运行到特定条件成立时结束循环。
循环分类:
- while
- repeat
- loop
循环控制:
- leave 类似于 break,跳出,结束当前所在的循环;
- iterate类似于 continue,继续,结束本次循环,继续下一次。
流程控制-循环-while
格式
1 | 【标签:】while 循环条件 do |
操作
1 | -- 选择 mydb7_procedure 数据库 |
流程控制-循环-repeat
格式
1 | [标签:]repeat |
操作
1 | -- -------存储过程-循环控制-repeat |
流程控制-循环-loop
格式
1 | [标签:] loop |
操作
1 | -- -------存储过程-循环控制-loop |
MySQL的索引
介绍
索引是通过某种算法,构建出一个数据模型,用于快速找出在某个列中有一特定值的行,不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行,表越大,查询数据所花费的时间就越多,如果表中查询的列有一个索引,MySQL能够快速到达一个位置去搜索数据文件,而不必查看所有数据,那么将会节省很大一部分时间。
索引类似一本书的目录,比如要查找’student’这个单词,可以先找到s开头的页然后向后查找,这个就类似索引。
索引的分类(按照实现的方式类分)
索引是存储引擎用来快速查找记录的一种数据结构,按照实现的方式类分,主要有Hash索引和B+Tree索引
Hash索引
Hash索引有时会产生Hash冲突,优化使用公式能降低冲突。
B+Tree索引
索引的分类(按照功能划分)
按照功能划分,索引划为以下分类:
索引的操作-创建索引-单列索引-普通索引
介绍
- 单列索引:一个索引只包含单个列,但一个表中可以有多个单列索引;
- 普通索引(NORMAL):MySQL中基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和空值,纯粹为了查询数据更快一点。
格式
1 | create database mydb5; |
索引的操作-查看索引-单列索引-普通索引
操作
1 | -- 1、查看数据库所有索引 |
索引的操作-删除索引
格式
1 | drop index 索引名 on 表名; |
操作
1 | drop index index_gender on student; |
索引的操作-创建索引-单列索引-唯一索引
介绍
唯一索引与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:
操作-创建索引
1 | -- 方式1-创建表的时候直接指定 |
操作-删除索引
1 | drop index index_card_id on student2 |
文章作者: [Blue Eagle]
文章链接: [https://yjh021.github.io/2024/10/04/MySQL/]
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 [Blue Eagle]