硬核学习 MySQL 之入门篇

这篇博客将结合MySQL命令和图形界面工具SQLyog来介绍 MySQL 的基本语法,案例将以学生数据库为代表,逐一介绍和分析 MySQL 数据的增删改查操作,如果仔细看完并认真理解,基本上已经可以进行数据库开发和操作了。在学习之前,如果对 MySQL 的安装、启动和登录不熟悉的话,可以先阅读我的另一篇博客 手把手教你安装和配置 MySQL 数据库

数据库相关术语:

学习数据库之前,我们需要先介绍和梳理一下数据库相关的一些专业术语,不然,有可能后面看着看着就不知道我在说什么了😏

数据库(database):真正存放数据的地方或者容器,里面由一张张不同数据类型的数据表组成

DBMS(数据库管理系统,Database Manage System):操作和管理数据库的软件,我们是不能够直接操作数据库的,所有的操作都是通过DBMS来操作。没错!MySQL就是其中一种DBMS,所以,千万别说MySQL是数据库了,它是管理和操作数据库的软件而已。

数据表(table):某种特定类型数据的结构化列表,比如包含学生各种信息的学生数据表,包含教师各种信息的教师数据表,这些表组合起来共同构成一个学校信息数据库。所以,数据表示数据库的子单元

注意:在同一个数据库中,表的名字是唯一,不可相同重复,但不同数据库之间可以有相同的表名字

模式(schema):关于数据库和表的布局及特性的信息

列(column):表中的一个字段(filed),数据表由列组成,所有表都是由一个或多个列组成的,而每一列存放着相同数据类型的数据

提示:列和字段是同一个概念,当别人说起字段的时候你要想到列是的意思,从专业的角度来说,我们在谈及数据表的列时应该使用字段术语,因为字段更符合标准,比如 anme字段、ID字段等,而不是 name列、ID列。所以后面的内容将统一为使用字段来表达列的意思。

行(row):数据表中的一条记录,表中的数据都是按行来存储的,可以把表想象成一张网格,每一列代表一个字段,每一行代表一条数据

主键(primary key):能够唯一区分表中每个行的字段,没错,主键就是一个字段,而且这个字段的值不能够重复,必须唯一区分

重点:任意一个字段都可以作为主键,只要它满足任意两行的值不同就可以了,当然,主键也可以有多个字段组成,使用多个字段作为主键的标准是:多个字段组合的值必须是唯一的


数据库操作命令

接下来,我将会从数据库的增、删、改、查这四个方面来介绍数据的操作命令

一、数据库的<增>

☕️ 查看数据库

增加数据库之前,我们先查看一下我们的数据库有哪些,查看数据的命令为:

SHOW DATABASES;
提示:MySQL语句以分号( ; )分割,而以分号( ; )或者\g结束,只有使用分号或者\g后按下回车才会执行命令。MySQL 不区分大小写,一般的原则是所有 SQL 关键字使用大写,而数据库名、表和字段使用小写,这样有助于阅读和调试;
由于我的MySQL是新安装的(使用的是MySQL8.0),所以会默认包含下面几个自带的数据库

在这里插入图片描述
这里先简单介绍一下这几个数据库的作用:

  • information_schema:是一个信息数据库,它保存着关于MySQL服务器所维护的所有其他数据库的信息(如:数据库名、数据库的表、表栏的数据类型与访问权限等)
  • mysql:MySQL的核心数据库,类似于sql server中的master表,主要负责存储数据库的用户、权限设置、关键字等mysql自己需要使用的控制和管理信息。mysql下有一张user表,里面包含了所有用户的信息,包括用户名和密码,所以我们可以直接在user表中修改用户的密码
  • performance_schema:主要用于收集数据库服务器性能参数
  • sys:sys库所有的数据源来自 performance_schema。目标是把performance_schema的复杂度降低,让DBA能更好的阅读这个库里的内容。让DBA更快的了解DB的运行情况

有兴趣进一步了解这四个数据库的话,可以去官网查看一下帮助文档,这里就不多介绍了。

☕️ 创建数据库

创建数据库的语句为:

CREATE DATABASE school;

创建好后,我们需要选择或者打开这个数据库:

USE school;

这样我们就进入到了 school 这个数据库了,USE database 这个命令不仅是打开进入数据库的命令,而且还是切换数据库的命令,比如,在 school 数据库中,直接使用 USE mysql;命令就会切换到 mysql 数据库中。

☕️ 创建数据表

新创建的数据库只是一个空的数据库,里面没有任何一张数据表,接下来我们添加一张学生数据表:

在这里插入图片描述
下面我们仔细分析一下创建表的语法,表的创建使用的是关键字 CREATE TABLE,后面紧跟表的名称,然后把表中所有字段写在括号( )中,括号后面的 ENGINE=INNODB 表示指定表的存储引擎类型,然后以分号表示 SQL 语句的结束。整条语句的重点应该就是括号中的字段写法以及括号后面的存储引擎,下面我们逐一分析这两个重点:

❄️ 字段写法

括号中的字段给出的方式为:字段名 + 字段数据类型 + 字段的约束,多条字段使用逗号分隔,最后一个可以不用逗号

字段名:字段名不能是 MySQL 的内置关键字和预留单词,如果想知道那些是关键字的话,可以参考官方文档给出的关键字:Keywords and Reserved Words。最尴尬的是连 name 这样的单词也是预留关键字,但我的表就只想用 name 怎么办?当然可以,我们可以使用顿号 ` 来去关键字操作,比如: `name` 就表示 name 解析为标识符而不是关键字了,或者像我的例子一样,使用一个前缀来避免和关键字重复。

字段数据类型:表示该字段所能存放数据类型,填写的类型必须是 MySQL 所支持的数据类型,MySQL 所支持的数据类型放在了文章的最后面,点击这里查看 MySQL数据类型,类型后面的括号数字表示类型的长度,比如 CHAR(10) 表示存储的字符串长度为10

数值长度:MySQL 支持数值型后面"指定长度",比如 INT(4) 表示检索的结果中显示该字段的数值时只显示4个字符,也就是说这个长度仅仅指的是显示的长度,并不会影响数值原来存储范围。而浮点型后面的括号 FLOAT(7,4) 则表示浮点型的显示精度,第一个数7表示显示的总长度为7,第二个数4表示小数点后面显示4个数字。如果没有指定显示长度,INT 默认为 INT(10),FLOAT/DOUBLE 默认为 (10, 0)

字段的约束:是对字段值的一种而外说明,比如 :

  • NULL:表明字段值可以为 NULL(空)
  • NOT NULL:表示字段值不能为空
  • AUTO_INCREMENT:表示每次执行 INSERT 数据插入时,自动对该字段增量
  • DEFAULT:给定一个默认值,如果插入数据时没有给出该字段的值,则使用 DEFAULT 后面的值
  • ZEROFILL:必须紧跟在数值类型(INT、FLOAT)之后,表示该字段的实际数值显示长度小于指定的数值长度时,使用0来填充

PRIMARY KEY (stu_id):表示指定作为主键的字段,可以指定多个字段作为主键

创建表成功后,我们使用表结构查看命令来看一下表的内部结构:

DESCRIBE students;
可以看到表内部所有字段及各属性情况

在这里插入图片描述
❄️ 存储引擎

创建表最后的 ENGINE=INNODB 表示指定表的数据操作引擎为 INNODB,数据库引擎是专门用来管理和处理数据操作的执行者,我们查询和更改操作都是数据库引擎实现的,而不同的数据库引擎具有不同的功能和特点,所以创建表时需要指定引擎,如果没有指定引擎,那么 MySQL 就会使用默认引擎(可能是MyISAM),下面列举了几个常用的数据库引擎:

  • InnoDB:可靠的事务处理引擎,但不支持全文本搜索
  • MyISAM:性能极高的引擎,但不支持事务处理,可支持全文本搜索
  • MEMORY:功能等同于 MyISAM,但由于数据存储在内存中,速度更快(适合用于临时表)
提示:MySQL语句中是忽略空格的,所以一条长SQL语句可以使用换行和每行使用 tab 缩进来使语句变得更容易阅读和编辑。在创建表的时候,指定的表名必须不存在,否则会出错,为了避免这种情况发生,可以在创建表的语句中添加判断条件关键字:IF NOT EXISTS,比如:CREATE TABLE IF NOT EXISTS students

❄️ SQL语句注释

在创建表的语句中我们还看到每个字段行后面有一个使用 # 号开头的说明,没错,那就是 MySQL 语句的注释,单行注释使用 # 号开头直到行末尾,多行注释使用 /* */,和 c/c++的注释类似


数据库的<删>

☕️ 删除数据库

数据库的删除命令为:

DROP DATABASE school;

如果删除的数据库不存在则会报错,所以删除之前应该判断一下是否存在:

DROP DATABASE IF EXISTS school;

☕️ 删除表

数据表的删除命令为:

DROP TABLE students;

同样如果删除的表不存在也会报错,所以相应地在删除之前应该判断一下是否存在:

DROP TABLE IF EXISTS students;
警告:删除数据库和数据表时一定要谨慎!因为删除是没有确认提示,也不能撤销的,执行之后就是永久删除了。所以千万别眼红或者手滑删错库了,别到时真的就成了从入门到删库跑路了


数据库的<改>

这里我们着重讲解和介绍数据表的更改操作,这里改的概念是对表的结构和数据进行更改,比如插入表数据、删除表数据或着增加删除字段。

📝 重命名数据表

重命名数据表的命令为:

RENAME TABLE oldtable TO newtable;

📝 添加新字段

使用命令 ALTER TABLE ADD 给表添加一列或者一个字段,比如在学生表中添加 stu_math 数学成绩字段:

ALTER TABLE students
ADD stu_math FLOAT NULL;

ADD 后面紧跟的内容和创建表时添加的字段形式一样,都是:字段名 + 字段数据类型 + 字段的约束

📝 删除字段

使用命令 ALTER TABLE DROP COLUMN 给表删除一列或者一个字段,ALTER TABLE 指定要更改的表名,DROP COLUMN 指定要删除的字段名(该字段必须存在,否则会报错),比如在学生表中删除刚才添加的 stu_math 数学成绩字段:

ALTER TABLE students
DROP COLUMN stu_math;

📝 插入行数据

使用命令 INSERT INTO VALUES 来 插入一条完整的行数据,INSERT INTO 后面紧跟要插入的表名,VALUES 提供插入的数据,比如:

INSERT INTO students
VALUES(1, "小明", "男", "3年级", "123456");

VALUES 后面的数据对应着每个字段的值,以这种方式插入的数据,必须对每个字段都提供一个值,并且根据字段在表中出现的顺序依次填充,如果不想提供某个字段的值,应该使用 NULL 值(如果对应字段允许 NULL 的话)填充。

上面的方法插入数据时不安全的,因为它要高度依赖表中字段定义的次序,如果表结构发生变动导致列的次序发生改变,那这种SQL语句就会出错。所以我们要使用一种更安全的方式插入数据:

INSERT INTO students(stu_id, stu_name, stu_sex, stu_class, stu_phone)
VALUES(2, "小英", "女", "2年级", "456789");

这种插入方式和前面的方式,功能上完全相同,不同的是,表名后面明确给出了字段名,插入数据 VALUES 中的数据,第一个值对应第一个指定的字段名,依次类推,这样就只需要指定字段和值对应匹配就可以了,不需要管表中字段的定义次序。(实际工作当中,我们应该使用这种安全的数据插入方式!

指定字段的插入方式还有另一种功能,回忆之前创建表时所说 字段约束,有些字段允许 NULL,有些字段虽然不允许空(NOT NULL)但提供了默认值,这些字段都可以在插入一行数据时不用提供该字段值,下面列出了可以省略字段值的条件:

  • 字段允许为 NULL(空)
  • 字段不允许空(NOT NULL),但提供了默认值 DEFAULT
  • 字段指定了 AUTO_INCREMENT,不管允不允许 NULL

所以下面的插入语句也是完全可以的:

INSERT INTO students(stu_name, stu_class)
VALUES("小花", "2年级");
得到的数据表如下:

在这里插入图片描述

重点讲解 AUTO_INCREMENT:以整形为例,MySQL会记录该字段的上一个值,如果上一个值没有的话就默认为1,后面如果不提供该字段的值时会根据前面的值加1。可以手动指定该字段的值,只要它是唯一的即可,并且该值将会替代自动生成的值,后续的增量会从该值开始。(我们可以使用 SELECT LAST_INSERT_ID(); 语句查看最后一个 AUTO_INCREMENT 值

插入多行数据:一次性插入多行数据时,只需要每组 VALUES 值使用括号括起来,并且使用逗号分隔开来:

INSERT INTO students(stu_name, stu_sex, stu_class)
VALUES("小张", "男", "2年级"),("小云", "女", "2年级");

📝 选择插入数据

INSERT INTO 还有另一种形式,就是可以将 SELECT 检索语句(后面会详细介绍)得到的结果插入到另一个表中,也就是所谓的 INSERT SELECT 语句,比如:

INSERT INTO students2(stu_id, stu_name)
SELECT stu_id, stu_name FROM students;

这里并不要求 students2 的列名要和 students 的列名一样,MySQL 并不关心列的名字,因为 SELECT 的第一列将会填充到插入表的第一列中,以此类推。这个操作实际上是把 students 的每一行数据插入到 students2 之中。

注意:INSERT INTO 后面表的字段名需要使用括号括起来,而 SELECT 后面的字段名是不用括号括起来的,唯一相同的是,每个字段都以逗号隔开。
提高插入性能:在有很多索引需要更新的时候,INSERT 操作可能会很耗时,并且会降低等待处理的 SELECT 语句的性能。如果检索操作比较重要的时候,可以通过在 INSERT INTO 中间添加关键字 LOW_PRIORITY 来指示MySQL降低 INSERT 语句的优先级,比如:INSERT LOW_PRIORITY INTO

📝 删除行数据

行的删除使用 DELETE 命令,而删除又分为特定行的删除,这些特定的行使用 WHERE 来指定删除那些行(WHERE 语句后面将会详细介绍),以及删除全部行数据。比如我们删除 stu_id 等于 1 的行:

DELETE FROM students
WHERE stu_id = 1;

删除全部数据有两种方法,第一种就是上面的删除方法,但不指定特定行:

DELETE FROM students;

DELETE 只是删除行数据,不会删除表!下面我们介绍另一种更快删除方法:

TRUNCATE TABLE students;

TRUNCATE TABLE 删除快的原因是:TRUNCATE 命令并不是逐行删除表中的数据,而是删除原来的表然后重新创建一个表。

📝 复制表

表的复制分为三种:

1、只复制表的结构

CREATE TABLE students2 LIKE students;

2、只复制表的数据

INSERT INTO students2 SELECT * FROM students

3、同时复制表和数据

CREATE TABLE students2 SELECT * FROM students;

📝 修改表数据

表数据的修改使用的是 UPDATE 关键字,更新有很多子操作,比如使用 SET 来设置字段的值:

UPDATE students SET stu_sex = ""
WHERE stu_id = 5;

UPDATE 选择要修改的表名,SET 设置 stu_sex 字段的值,WHERE 指定修改的字段位于那一行,如果没有 WHERE 来限定修改的行,则会修改该所有行的该字段值,相当于修改整列值,如果加上修改的值为 NULL 就相当于删除整列值了:

UPDATE students SET stu_sex = NULL;

所以修改值时要小心,尽量使用限定行的 UPDATE 语句。如果要修改多个字段的值,只需加在 SET 后面即可,使用分号隔开,最后一列不用逗号:

UPDATE students
SET stu_sex = "", stu_phone = "123456"
WHERE stu_id = 5;
IGNORE 关键字:使用 UPDTAE 更新多行的时候,如果其中的一行或者多行出错时,整个 UPDATE 都会被取消(发生错误之前更新的所有行都会恢复到原来的值),如果想要即使发生错误也继续进行更新可以使用 IGNORE 关键字,比如:UPDATE IGNORE students

数据库的<查>

终于进入数据库最重要同时也是最复杂的环节了,因为数据库最核心的技术就是查询技术,只有在茫茫数据库中找出正确的数据,才能进行其他关键操作,比如:修改和删除数据。如果数据查找出错,那将是最糟糕的事情,试想一下,本来想修改A用户的数据却错改了B用户的数据以及本想删除一个用户的数据却把全部用户的数据都删除了,内心基本上就是有种删库跑路的节奏呀!😂,好了,不扯了,下面开始进入查询命令吧。

☁️ SELECT 语句

SELECT 和 FROM 关键字组成语句,是专门用来检索列的语句,所以接在 SELECT 后面的就是需要检索的字段名,而 FROM 后面的就是需要检索的表,比如从学生表中检索学生姓名这一列的值:

SELECT stu_name FROM students;

结果如下:
在这里插入图片描述
为什么名字变成了英文了?不要在意细节,只是后面的讲解会越来越复杂,所以为了简洁起见,特地把表的结构改了一下!好了,废话不多说了,介绍了单列检索下面介绍多列检索:只需要把所要检索的字段名添加在 SELECT 后面并使用逗号隔开即可:

SELECT stu_id, stu_name, stu_math FROM students;

结果如下:
在这里插入图片描述
如果想要检索所有列,直接使用通配符( * )来代替字段名就可以了:

SELECT * FROM students;

从上面的检索结果可以发现,stu_math 字段的结果有重复数字的,如果想要检索的结果中不重复(即值唯一)的话,可以在 SELECT 后面添加关键字 DISTINCT 来指示MySQL返回的结果唯一:

SELECT DISTINCT stu_math FROM students;

检索得到的结果将不会重复:
在这里插入图片描述

注意:关键字 DISTINCT 作用于它前面的所有字段,比如: SELECT DISTINCT stu_math, stu_art FROM students; 关键字 DISTINCT 会作用于 stu_math 和 stu_art 两个字段,即:DISTINCT 会比较这两个字段的值,这两个字段的值都一样才会被过滤,只要有一个值不相同都会被检索出来,这是需要牢记的。

☁️ 限制检索结果

如果没有设置限制的话,SELECT 会返回检索的所有结果,如果想限制返回的个数,需要使用关键字 LIMIT,比如:限制只返回检索结果中的前3条:

SELECT stu_id, stu_name FROM students LIMIT 3;

输出结果为:
在这里插入图片描述
当然,我们还可以指定开始检索的行数:

SELECT stu_name FROM students LIMIT 2,3;

这样我们得到的结果就是从第2行开始的3条记录,注意:检索的结果行数是从0开始数起的,所以2表示第3表结果
在这里插入图片描述
为了区分这两个数字的含义,MySQL 还支持另一种更加清晰的写法:

SELECT stu_name FROM students LIMIT 3 OFFSET 2;

LIMIT 3 表示只检索3行,OFFSET 表示从第2行开始检索

重要提示:LIMIT 只带一个数字时,返回的起始位置为第一行开始;检索的结果是从0开始算起的,所以 LIMIT 1,1 返回的是第二行结果;指定的结果数大于实际检索的数量时,返回全部结果数;

☁️ 使用完全限定名

所谓完全限定名,就是限定检索的字段属于哪张表,和限定检索的表属于哪个数据库,比如限定检索字段:

SELECT students.stu_name FROM students;

同时限定字段和表:

SELECT students.stu_name FROM school.students;

☁️ 检索排序

检索出的数据一般是以它在底层表中出现的顺序显示的,可以是数据添加到表中时的顺序,但如果数据后来被更新或者删除就会受到MySQL重用回收存储空间的影响。在介绍排序命令时,我们先了解一下一个概念:

子句(Clause):SQL 语句由子句构成,有些是必须的,有些是可选的。一个子句由关键字和提供的数据组成,比如我们的 SELECT 语句中的 FROM 语句就是一个子句。

数据的排序使用的是 ORDER BY 子句,比如下面的检索结果按照姓名排序:

SELECT stu_name, stu_math FROM students
ORDER BY stu_name;

得到的结果按照姓名排序:
在这里插入图片描述
由于指定的排序字段 stu_name 是字符类型,所以 MySQL 会对结果按照字母顺序来排序:先比较第一个字符,如果第一个字符相同则比较第二个字符,一次类推下去。如果指定的字段为数字类型,则直接比较数值大小即可。当然,ORDER BY 子句还可以指定多个排序字段:

SELECT stu_id, stu_math, stu_name FROM students
ORDER BY stu_math, stu_name;

在这里插入图片描述
从结果可以看出,多个排序字段的情况下,首先按照第一个字段 stu_math 进行排序,如果该字段的值相同情况下,则按照第二个字段 stu_name 进行排序。相应的,如果第一个排序字段的值是唯一的,则不会对第二个排序字段进行排序。

☁️ 指定排序方向

默认的排序结果为升序排序(从小到达)其对应的关键字为 ASC(ascending),如果想要进行降序排序(从大到小),则必须使用 DESC(descending) 关键字,用法是 DESC 关键字紧跟需要降序排序的字段后面,比如按照数学成绩降序排序:

SELECT stu_id, stu_math, stu_name FROM students
ORDER BY stu_math DESC;

在这里插入图片描述
可以看到整个排序结果是按照数学成绩从大到小降序进行排序的。多个字段排序也是一样,比如:按照数学成绩进行降序排序,如果数学成绩相同则按照学生姓名进行升序排序:

SELECT stu_id, stu_math, stu_name FROM students
ORDER BY stu_math DESC, stu_name ASC;

在这里插入图片描述

提示:由于默认排序是升序排序,所以使不使用关键字 ASC 效果都一样;关键字 DESC 和 ASC 只作用于一个字段,即它所紧跟的前面的那个字段,如果想要多个排序字段都使用降序的话,每个字段都要指定 DESC 关键字。

ORDER BY 与 LIMIT 结合找出最值,比如使用降序找出最高的数学成绩:

SELECT stu_math FROM students
ORDER BY stu_math DESC
LIMIT 1;
重点:子句的出现顺序为:如果有 ORDER BY 子句,则应该保证它位于 FROM 子句之后,如果使用了 LIMIT,则它必须位于 ORDER BY 之后。如果子句的次序不对将会产生错误信息。

☁️ WHERE 语句

检索数据的时候,我们往往需要制定搜索条件(search criteria),搜索条件也称为过滤条件(filter condition)。在 SELECT 语句中,通过使用 WHERE 子句指定的搜索条件来过滤数据,比如检索 stu_id 为2的整条学生数据:

SELECT * FROM students WHERE stu_id = 2;

这样就得到了一条学生ID为2的数据:
在这里插入图片描述

提示:当同时使用 WHERE 和 ORDER BY 语句的时候,应该让 ORDER BY 位于 WHERE 之后,否则将会出错。

☁️ WHERE 语句操作符

WHERE 语句使用操作符来对数据进行过滤,比如前面看到的 WHERE stu_id = 2 使用的就是相等操作符(没错!MySQL使用的是 = 来表示相等,而不是编程语言所使用的 ==),下面列出了 WHERE 语句支持的条件操作符:

=等于
!=不等于
<>等价于 !=
<小于
<=小于等于
>大于
>=小于等于
BETWEEN AND在指定的两个值之间
注意:由于MySQL在执行匹配的时候是不区分大小写的,所以,如果使用 WHERE stu_name = 'Jack' 来进行检索时,'Jack','JACK' 之类的都会匹配出来。

☁️ 范围值检索

如果想要对某个范围区间进行检索,可以使用 BETWEEN AND 操作符,即提供开始值和结束值,例如检索 stu_id 在 2 和 4 之间的学生数据:

SELECT * FROM students
WHERE stu_id BETWEEN 2 AND 4;

这样就检索出学生ID为2到4之间的数据:
在这里插入图片描述
☁️ 空值判断

SELECT 语句有一个特殊的 WHERE 子句,可用来检索值为 NULL 的结果数据,这个子句就是 IS NULL 子句,比如检索英语成绩为空的数据:

SELECT * FROM students
WHERE stu_eng IS NULL;

检索得到所有 stu_eng 值为空的数据:
在这里插入图片描述

注意:值为空(NULL),表示意思是没有值,和整数0、空字符串"",之间的含义是不同的,0和空字符串是有值的数据,而 NULL 指的是没有值的意思。

☁️ 逻辑操作符

在 WHERE 语句中可以使用逻辑操作符(logical operator)来组合多条过滤条件,下面将逐一介绍这些组合逻辑操作符:

AND 操作符

AND 是用在WHERE子句中的关键字,用来指示检索需要满足所有给定的条件进行,可以组合使用多个 AND 来给定多个条件,并且每个条件都必须满足。比如检索数学成绩大于80分并且英语成绩大于85分的所有行数据:

SELECT * FROM students
WHERE stu_math >= 80 AND stu_eng >= 85;

OR 操作符

OR 操作符与 AND 操作符不同,它指示 MySQL 检索匹配其中任意一个条件即可,比如检索数学成绩大于60或者英语成绩大于70的所有行数据:

SELECT * FROM students
WHERE stu_math >= 60 OR stu_eng >= 70;
计算次序:在混合使用 AND 和 OR 操作符的时候,MySQL 会优先计算 AND 操作符然后再计算 OR 操作符,比如:WHERE stu_math > 60 OR stu_eng > 70 AND stu_art < 90,会被解释为 WHERE (stu_math > 60) OR (stu_eng > 70 AND stu_art < 90),所以这一点是需要注意。为了避免出现这种不明确的含义,可以明确地给出括号来进行分组,这样就可以消除歧义。

IN 操作符

IN 操作符用来指定条件范围,范围值使用逗号分隔并用圆括号括起来,表示括号中的每个值都可以匹配。比如检索数学成绩为80或者90的所有行数据:

SELECT * FROM students
WHERE stu_math IN (80, 90);

IN 操作符的效果相当于 OR 操作符,上面的条件也可以写成:WHERE stu_math = 80 OR stu_math = 90,那为什么要使用 IN 操作符呢?因为使用 IN 操作符有以下几个优点:

  • 在使用多个长选项组合时,IN 操作符的语句比较清晰直观
  • 使用 IN 操作符可以更容易管理计算次序(因为使用的操作符更少)
  • IN 操作符比OR操作符执行速度更快
  • IN 最大的优点是可以包含其他 SELECT 语句,使得能够更动态建立 WHERE 语句

NOT 操作符

NOT 操作符的主要功能是否定跟在它后面的条件关键字,最常用的是 NOT 与 IN 组合使用来排除条件,比如排除数学成绩为80或90的数据:

SELECT * FROM students
WHERE stu_math NOT IN (80, 90);
MySQL 的 NOT 操作符支持对 IN、BETWEEN 和 EXISTS 字句取反

☁️ 通配符

我们先来了解一下两个专业术语:

  • 通配符(wildcard):用来匹配值的一部分特殊字符
  • 搜索模式(search pattern):有字面值、通配符或者两者组合构成的搜索条件

MySQL 中使用 LIKE 操作符来指示后面跟的搜索模式为统配符匹配,MySQL 支持的统配符有:百分号(%)通配符和下划线(_)通配符,统配符的搜索模式所作用的对象是值的类型为字符型的字段

百分号通配符

百分号 % 表示匹配任何字符出现任意次数(匹配的字符数可以是0个、1个或多个),比如:检索学生姓名中所有以 Jac 开头的行数据:

SELECT * FROM students
WHERE stu_name LIKE "Jac%";

检索模式为:“Jac%”,Jac 表示词的开头为 Jac,% 告诉 MySQL 接受 Jac 之后的任意字符,不管它出现有多少字符,所以这个模式可以检索出姓名为 Jack、Jacimy 等所有以 Jac 开头的结果。

注意:MySQL 的统配符匹配模式默认是不区分大小写的,但可以通过配置来支持区分大小写,统配符可以放在任意位置,并且可以多个统配符同时使用,如果放在两端:"%head%"表示任何任何位置包含文本 head 的值,如果放在中间:"h%d"表示匹配所有以 h 开头 d 结尾的值。("%" 可以匹配任何东西但不匹配 NULL 值)

下划线通配符

下划线 (_) 通配符的用途和 % 的用途一样,只是,下划线要求匹配1个并且必须匹配1个字符,不能多也不能少。比如:

SELECT * FROM students
WHERE stu_name LIKE "_ack";

这个匹配模式匹配的结果为 Jack、Lack 之类的,ack 之前的字符必须有一个且只能是一个。

统配符的使用技巧

  • 不要过度使用通配符,如果其他操作符可以达到相同目的的话,应该使用其他操作符
  • 尽量不要把通配符放在搜索模式的开头,因为这会让搜索速度变慢
  • 想要搜索更加准确,应该仔细注意通配符的放置位置

☁️ 正则表达式

如果不了解正则表达式的话可以参考我的另一篇博客:一篇文章教你学会【正则表达式】,看懂我的这篇正则表达式之后,后面的 MySQL 正则表达式匹配就很简单了,只需要使用关键字 REGEXP 后面跟正则表达式字符串即可,语法和 LIKE 操作符一样。比如搜索名字中连续出现2个 a 或者连续出现3个 b 的值:

SELECT * FROM students
WHERE stu_name REGEXP "(a{2})|(b{3})";

有些搜索条件既可以使用 LIKE 操作符,也可以使用正则表达式,但相比于 LIKE 操作符,正则表示式搜索能力更强大更灵活1

注意:多数正则表达式使用的是单个反斜杠来转义特殊字符,比如 \. 表示转义元字符 ( . ), 但在 MySQL 中使用两个反斜杠来转义:\\. \\* \\n (MySQL 自己解释一个,正则表达式库解释一个)


MySQL 所支持的数据类型


字符串数据类型
CHAR 1~255个字符的定长串,它的长度必须在创建时指定,否则MySQL假定为CHAR(1)
ENUM 接受最多64K个串组成的一个预定义集合的某个串
TEXT 最大长度为64K的变长文本
LONGTEXT 与TEXT相同,但最大长度为4GB
MEDIUMTEXT 与TEXT相同,但最大长度为16K
TINYTEXT 与TEXT相同,但最大长度为255字节
SET 接受最多64个串组成的一个预定义集合的零个火多个串
VARCHAR 长度可变,最多不超过255字节,如果创建时指定为VARCHAR(n),则可存储0到n个字符的变长串(n<=255)

数值数据类型
BIT 位字段,1~64位
INT(或INTEGER) 整数型,4字节共32位,有符号范围为-2147483648~2147483648,无符号范围为0~4294967295
TYNYINT 整数型,1字节8位,有符号范围为-127~128,无符号范围为0~255
SMALLINT 整数型,2字节16位, 有符号复位为-32768~32768,无符号范围为0~65536
MEDIUMINT 整数型,3字节24位,有符号范围为-8388608~8388608, 无符号范围为0~16777216
BIGINT 整数型,8字节64位,有符号范围为-9223372036854775808~9223372036854775808,无符号范围为0~18446744073709551615
BOOLEAN(或BOOL) 布尔型,值为0或1,用于开/关(on/off)标志
FLOAT 单精度浮点值
DOUBLE 双精度浮点值
DECIMAL 精度可变的浮点值
REAL 4字节的浮点值
除了 BIT 和 BOOLEAN 之外,都可以有符号或者无符号,指定为无符号类型时可以使用 UNSIGNED关键字

日期和时间数据类型
DATE 表示1000-10-01~9999-12-31的日期,格式为 YYYY-MM-DD
TIME 格式为 HH:MM:SS
YEAR 用2为数字表示时,范围为70(1970年)~69(2069年);用4位数字表示时,范围是 1901年~1255年
DATETIME DATE 和 TIME 的结合
TIMESTAMP 功能和 DATETIME 相同,但范围较小

二进制数据类型
BLOB Blob最长长度为64KB
TINYBLOB Blob最长长度为255字节
MEDIUMBLOB Blob最长长度为16MB
LONGBLOB Blob最长长度为4GB
二进制数据类型可以存储任何数据,包括图像、多媒体、字符文档等
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章