MySQL基础
MySQL基础
数据库的相关概念
为什么要使用数据库:
- 持久化(persistence):把数据保存到可掉电式存储设备中以供之后使用。
- 持久化的主要作用是将内存中的数据存储在关系型数据库中,或存储在磁盘文件、XML数据文件中。
DB:数据库(Database)
- 即存储数据的“仓库”,其本质是一个文件系统。它保存了一系列有组织的数据。
DBMS:数据库管理系统(Database Management System)
- 是一种操纵和管理数据库的大型软件,用于建立、使用和维护数据库,对数据库进行统一管理和控制。用户通过数据库管理系统访问数据库中表内的数据。
SQL:结构化查询语言(Structured Query Language)
- 专门用来与数据库通信的语言。
关系型数据库(RDBMS):
- 这种类型的数据库是最古老的数据库类型,关系型数据库模型是把复杂的数据结构归结为简单的二元关系 (即二维表格形式)。
- 关系型数据库以 行(row) 和 列(column) 的形式存储数据,以便于用户理解。
- 优势:
- 复杂查询可以用SQL语句方便的在一个表以及多个表之间做非常复杂的数据查询。
- 事务支持使得对于安全性能很高的数据访问要求得以实现。
- 典型代表mysql、oracle、sql server等。
非关系型数据库(非RDBMS):
- 非关系型数据库,可看成传统关系型数据库的功能阉割版本,基于键值对存储数据,不需要经过SQL层的解析性能非常高 。同时,通过减少不常用的功能,进一步提高性能。
- 键值型数据库:
- 键值型数据库通过 Key-Value 键值的方式来存储数据,其中 Key 和 Value 可以是简单的对象,也可以是复杂的对象。
- 键值型数据库典型的使用场景是作为内存缓存 。 Redis 是最流行的键值型数据库。
- 文档型数据库:
- 此类数据库可存放并获取文档,可以是XML、JSON等格式。在数据库中文档作为处理信息的基本单位, 一个文档就相当于一条记录。
- MongoDB 是最流行的文档型数据库。此外,还有CouchDB等。
- 搜索引擎数据库:
- 虽然关系型数据库采用了索引提升检索效率,但是针对全文索引效率却较低。搜索引擎数据库是应用在 搜索引擎领域的数据存储形式,由于搜索引擎会爬取大量的数据,并以特定的格式进行存储,这样在检 索的时候才能保证性能最优。核心原理是“倒排索引”。
- 典型产品:Solr、Elasticsearch、Splunk 等。
- 列式数据库、图形数据库
mysql字符编码问题:
在MySQL 8.0版本之前,默认字符集为latin1,utf8字符集指向的是utf8mb3。网站开发人员在数据库设计的时候往往会将编码修改为utf8字符集。如果遗忘修改默认的编码,就会出现乱码的问题。从MySQL 8.0 开始,数据库的默认编码改为 utf8mb4 ,从而避免了乱码问题。
MySQL主要目录结构
MySQL的目录结构 | 说明 |
---|---|
bin目录 | 所有MySQL的可执行文件。如:mysql.exe |
MySQLInstanceConfig.exe | 数据库的配置向导,在安装时出现的内容 |
data目录 | 系统数据库所在的目录 |
my.ini文件 | MySQL的主要配置文件 |
c:\ProgramData\MySQL\MySQL Server 8.0\data\ | 用户创建的数据库所在的目录 |
SQL分类
DDL:数据定义语言。
- CREATE \ ALTER \ DROP \ RENAME \ TRUNCATE
DML:数据操作语言。
- INSERT \ DELETE \ UPDATE \ SELECT
DCL:数据控制语言。
- COMMIT \ ROLLBACK \ SAVEPOINT \ GRANT \ REVOKE
SELECT语法
导入现有的sql文件:source 文件的全路径名
- SELECT … FROM 基础使用
- AS:设置别名,可以省略(只能在ORDER BY中使用,不能再WHERE中使用)
- DISTINCT:去除重复行
- DESCRIBE 表名/DESC 表名:显示表的结构
- WHERE:过滤数据
1 | SELECT DISTINCT department_id AS "部门id" FROM employees WHERE department_id>10; |
注:1、所有运算符或列值遇到null值,运算的结果都为null。2、表中的字段、表名等和保留字、数据库系统或常用方法冲突,在SQL语句中使用一对``(着重号)引起来。
运算符
比较运算符
比较运算符用来对表达式左边的操作数和右边的操作数进行比较,比较的结果为真则返回1,比较的结果为假则返回0,其他情况则返回NULL。
关键字的使用:
1 | SELECT * FROM employees WHERE commission_pct IS NULL; |
LIKE关键字使用补充:
- “%”:匹配0个或多个字符。
- “_”:只能匹配一个字符。
逻辑运算符
逻辑运算符主要用来判断表达式的真假,在MySQL中,逻辑运算符的返回结果为1、0或者NULL。
排序与分页
排序
使用 ORDER BY进行排序,默认为升序排序。
- ASC(ascend):升序
- DESC(descend):降序
1 | SELECT last_name,department_id FROM employees ORDER BY department_id; |
注:1、可以使用列的别名,进行排序。2、WHERE 需要声明在FROM后,ORDER BY之前。
使用ORDER BY对多列进行排序
- 对多列进行排序,首先排序的第一列必须有相同的列值才会对第二列进行排序。
1 | SELECT last_name,salary,department_id |
分页
使用LIMIT关键字将查询返回的结果集一段一段显示出来。
- 格式:LIMIT 位置偏移量,行数
- 需求:每页显示pageSize条记录,此时显示第pageNo页
- 公式:LIMIT (pageNo-1) * pageSize,pageSize;
1 | # 查询前20条记录 |
注:LIMIT第一个参数可以省略,默认从第一条记录开始。
SQL语句执行顺序:FROM….WHERE….SELECT….ORDER BY…LIMIT
多表查询
多表查询,也称为关联查询,指两个或更多个表一起完成查询操作。
前提条件:这些一起查询的表之间是有关系的(一对一、一对多),它们之间一定是有关联字段,这个关联字段可能建立了外键,也可能没有建立外键。比如:员工表和部门表,这两个表依靠”部门编号”进行关联。
如果缺少了多表的连接条件会出现出现笛卡尔积错误,每个员工都与每个部门匹配了一遍。
1 | SELECT employee_id,department_name |
等值连接
多表查询的正确方式:添加连接条件
等值连接条件:
1 | SELECT employee_id,department_name |
如果查询语句中出现了多个表中都存在的字段,则必须指明此字段所在的表。
1 | # 指明部门id所在表 |
建议:从sql优化的角度,建议多表查询时,每个字段前都指明其所在的表。
1 | SELECT employees.employee_id,departments.department_name,employees.department_id |
可以对表使用别名提高可读性:在SELECT和WHERE中使用表的别名
1 | # 查询所有员工的id以及所在的部门名称和部门id |
注:如果给表起了别名,则在SELECT或WHERE中必须使用表的别名,而不能再使用表的原名。
结论:如果有n个表实现多表的查询,则需要至少n-1个连接条件。
非等值连接
非等值连接条件:
1 | # 查询所有员工的姓名、薪资、薪资等级 |
自连接
两张相同的表进行连接。
1 | # 查询员工的id和姓名以及其管理者的id和姓名 |
内连接
合并具有同一列的两个以上的表的行, 结果集中不包含一个表与另一个表不匹配的行。
1 | SELECT 字段列表 |
外连接
两个表在连接过程中除了返回满足连接条件的行以外还返回左(或右)表中不满足条件的 行 ,这种连接称为左(或右) 外连接。没有匹配的行时, 结果表中相应的列为空(NULL)。
- 如果是左外连接,则连接条件中左边的表也称为主表 ,右边的表称为从表 。
1 | #左外连接 |
- 如果是右外连接,则连接条件中右边的表也称为 主表 ,左边的表称为 从表。
1 | #右外连接 |
- 如果是满外连接,则左右表匹配的数据 + 左表没有匹配到的数据 + 右表没有匹配到的数据。
1 | LEFT JOIN UNION RIGHT join |
UNION的使用
合并查询结果,利用UNION关键字,可以给出多条SELECT语句,并将它们的结果组合成单个结果集。合并时,两个表对应的列数和数据类型必须相同,并且相互对应。各个SELECT语句之间使用UNION或UNION ALL关键字分隔。
1 | SELECT column,... FROM table1 |
- UNION 操作符返回两个查询的结果集的并集,去除重复记录。
- UNION ALL操作符返回两个查询的结果集的并集。对于两个结果集的重复部分,不去重。
SQL99语法新特性
自然连接
SQL99 在 SQL92 的基础上提供了一些特殊语法,比如 NATURAL JOIN 用来表示自然连接。我们可以把 自然连接理解为 SQL92 中的等值连接。它会帮你自动查询两张连接表中 所有相同的字段 ,然后进行等值连接 。
1 | SELECT employee_id,last_name,department_name |
USING连接
当我们进行连接的时候,SQL99还支持使用 USING 指定数据表里的同名字段进行等值连接。但是只能配 合JOIN一起使用。
1 | SELECT employee_id,last_name,department_name |
关联查询小结
表连接的约束条件可以有三种方式:WHERE, ON, USING
- WHERE:适用于所有关联查询。
- ON :只能和JOIN一起使用,只能写关联条件。虽然关联条件可以并到WHERE中和其他条件一起写,但分开写可读性更好。
- USING:只能和JOIN一起使用,而且要求两个关联字段在关联表中名称一致,而且只能表示关联字段值相等。
1 | #关联条件 |
单行函数
介绍
单行函数特点:
- 操作数据对象
- 接受参数返回一个结果
- 只对一行进行变换
- 每行返回一个结果
- 可以嵌套参数可以是一列或一个值
数值函数
- abs(x):返回x的绝对值
- CEIL(x) / FLOOR(x) :向上/向下取整
- MOD(x, y):MOD(x,y)
- RAND():返回0~1内的随机数
- ROUND(x, y):求参数x的四舍五入的值,保留y位小数
字符串函数
- TRIM(str):去除s字符串的首尾空格
- CONCAT(S1,S2,…Sn):字符串拼接,将S1,S2,… Sn拼接成一个字符串
- UPPER(str) / LOWER(str):将字符串str全部转为大/小写
- LPAD(str, n, pad):左填充,用字符串pad对str的左边进行填充,达到n个字符串长度
- RPAD(str,n,pad):右填充,用字符串pad对str的右边进行填充,达到n个字符串长度
- SUBSTRING(str,start,len):返回从字符串str从start位置起的len个长度的字符串
- LEFT(str,len)/RIGHT(str,len):返回字符串str从最左边/右边开始的len长度字符串
日期时间函数
now():返回当前日期和时间
CURDATE():返回当前日期
CURTIME():返回当前时间
YEAR(date) / MONTH(date) / DAY(date):获取指定date的年/月/日
DATE_ADD(date, INTERVAL expr type):返回一个日期/时间值加上一个时间间隔expr后的时间值
DATEDIFF(date1, date2):返回起始时间date1 和 结束时间date2之间的天数
流程控制函数
IF(value,value1,value2):如果value的值为TRUE,返回value1, 否则返回value2
IFNULL(value1 , value2):如果value1不为空,返回value1,否则返回value2
CASE WHEN [ val1 ] THEN [res1] … ELSE [ default ] END:如果val1为true,返回res1,… 否则返回default默认值
CASE [ expr ] WHEN [ val1 ] THEN [res1] … ELSE [ default ] END:如果expr的值等于val1,返回 res1,… 否则返回default默认值
加密解密函数
- MD5(str):返回字符串str的md5加密后的值,也是一种加密方式。若参数为 NULL,则会返回NULL
MySQL信息函数
- VERSION():返回当前MySQL的版本号
其他函数
- FORMAT(value, n):返回对数字value进行格式化后的结果数据。n表示 四舍五入 后保留 到小数点后n位
聚合函数
聚合(或聚集、分组)函数,它是对 一组数据进行汇总的函数,输入的是一组数据的集合,输出的是单个值。
- avg()
- sum()
- max()
- min()
- count()
group by
GROUP BY
是 SQL 中的一个关键字,用于结合聚合函数对查询结果进行分组。它通常与聚合函数(如 COUNT()
、SUM()
、AVG()
等)一起使用,以便对特定组的数据进行汇总或计算。
语法:
1 | SELECT column1, aggregate_function(column2) |
having
HAVING
是 SQL 中用于对分组数据进行筛选的关键字,通常与 GROUP BY
一起使用。它允许在已经分组的结果集上对分组进行过滤,类似于 WHERE
条件,但 HAVING
用于对分组后的结果进行条件过滤。
语法:
1 | SELECT column1, aggregate_function(column2) |
WHERE和HAVING的对比:
- WHERE 可以直接使用表中的字段作为筛选条件,但不能使用分组中的计算函数作为筛选条件; HAVING 必须要与 GROUP BY 配合使用,可以把分组计算的函数和分组字段作为筛选条件。
- 这决定了,在需要对数据进行分组统计的时候,HAVING 可以完成 WHERE 不能完成的任务。这是因为, 在查询语法结构中,WHERE 在 GROUP BY 之前,所以无法对分组结果进行筛选。HAVING 在 GROUP BY 之 后,可以使用分组字段和分组中的计算函数,对分组的结果集进行筛选,这个功能是 WHERE 无法完成 的。另外,WHERE排除的记录不再包括在分组中。
- 如果需要通过连接从关联表中获取需要的数据,WHERE 是先筛选后连接,而 HAVING 是先连接 后筛选。
- 这一点,就决定了在关联查询中,WHERE 比 HAVING 更高效。因为 WHERE 可以先筛选,用一 个筛选后的较小数据集和关联表进行连接,这样占用的资源比较少,执行效率也比较高。HAVING 则需要 先把结果集准备好,也就是用未被筛选的数据集进行关联,然后对这个大的数据集进行筛选,这样占用 的资源就比较多,执行效率也较低。
SQL查询语法书写顺序
- SELECT:选择要返回的列。
- FROM:指定要查询的表。
- WHERE:设置过滤条件,以限制返回的行。
- GROUP BY:对结果集进行分组。
- HAVING:对分组结果进行过滤。
- JOIN:连接其他表。
- ORDER BY:对结果集进行排序。
- LIMIT / OFFSET:限制返回的行数。
SQL查询语句执行流程
- FROM:从哪个表中选取数据。
- JOIN:把哪些表连接起来。
- WHERE:过滤掉不需要的数据。
- GROUP BY:按照哪个字段进行分组。
- HAVING:在分组之后过滤数据。
- SELECT:选取哪些字段。
- DISTINCT:去重处理。
- UNION:联合另一个查询。
- ORDER BY:按照哪个字段进行排序。
- LIMIT:选取前几条记录。
子查询
介绍
SQL语句中嵌套SELECT语句,称为嵌套查询,又称子查询。
子查询外部的语句可以是INSERT / UPDATE / DELETE / SELECT 的任何一个。
标量子查询
子查询返回的结果是单个值(数字、字符串、日期等),最简单的形式,这种子查询称为标量子查询。
等于、大于、大于等于、小于、小于等于、不等于与子查询结果比较
示例:
1 | SELECT * |
列子查询
子查询返回的结果是一列(可以是多行),这种子查询称为列子查询。
in、not in、any、all、some与子查询结果比较
示例:
1 | SELECT * |
相关子查询
如果子查询的执行依赖于外部查询,通常情况下都是因为子查询中的表用到了外部的表,并进行了条件关联,因此每执行一次外部查询,子查询都要重新计算一次,这样的子查询就称之为关联子查询 。
相关子查询按照一行接一行的顺序执行,主查询的每一行都执行一次子查询。
示例:
1 | SELECT |
相关更新
相关更新用于更新基于主查询结果的子查询数据。下面是一个相关更新的示例:
1 | UPDATE table1 |
相关删除
相关删除用于基于主查询结果删除相关联的数据。下面是一个相关删除的示例:
1 | DELETE FROM table1 |
创建表和管理表
数据库操作
mysql中的数据类型
创建数据库并指定字符集
- CREATE DATABASE 数据库名 CHARACTER SET 字符集;
修改数据库更改字符集
- ALTER DATABASE 数据库名 CHARACTER SET 字符集; #比如:gbk、utf8等
表操作
创建表
1 | CREATE TABLE [IF NOT EXISTS] 表名( |
查看数据表创建结构
- SHOW CREATE TABLE 表名
修改表
追加一列:ALTER TABLE 表名 ADD 【COLUMN】 字段名 字段类型 【FIRST|AFTER 字段名】;
修改一列:ALTER TABLE 表名 MODIFY 【COLUMN】 字段名1 字段类型 【DEFAULT 默认值】【FIRST|AFTER 字段名 2】;
重命名列:ALTER TABLE 表名 CHANGE 【column】 列名 新列名 新数据类型;
删除一列:ALTER TABLE 表名 DROP 【COLUMN】字段名;
重命名表
- RENAME TABLE emp TO myemp;
删除表
- DROP TABLE [IF EXISTS] 数据表1 [, 数据表2, …, 数据表n];
清空表
- TRUNCATE TABLE detail_dept;
数据处理-增删改
插入数据
- 情况1:为表的所有字段按默认顺序插入数据
1 | INSERT INTO 表名 |
- 情况2:为表的指定字段插入数据
1 | INSERT INTO 表名(column1 [, column2, …, columnn]) |
- 情况3:同时插入多条记录
1 | INSERT INTO table_name |
小结:
- VALUES 也可以写成 VALUE ,但是VALUES是标准写法。
- 字符和日期型数据应包含在单引号中。
将查询结果插入到表中
INSERT还可以将SELECT语句查询的结果插入到表中,此时不需要把每一条记录的值一个一个输入,只需 要使用一条INSERT语句和一条SELECT语句组成的组合语句即可快速地从一个或多个表中向一个表中插入多行。
1 | INSERT INTO 目标表名 |
小结:
- 在 INSERT 语句中加入子查询。
- 不必书写 VALUES 子句。
- 子查询中的值列表应与 INSERT 子句中的列名对应。
更新数据
1 | UPDATE table_name |
- 可以一次更新多条数据。
- 如果需要回滚数据,需要保证在DML前,进行设置:SET AUTOCOMMIT = FALSE;
- 使用 WHERE 子句指定需要更新的数据。
删除数据
1 | DELETE FROM table_name [WHERE <condition>]; |
MySQL8新特性-计算列
什么叫计算列呢?简单来说就是某一列的值是通过别的列计算得来的。例如,a列值为1、b列值为2,c列 不需要手动插入,定义a+b的结果为c的值,那么c就是计算列,是通过别的列计算得来的。
举例:定义数据表tb1,然后定义字段id、字段a、字段b和字段c,其中字段c为计算列,用于计算 a+b 的值。 首先创建测试表tb1,语句如下:
1 | CREATE TABLE tb1( |
只需要插入a,b字段数据,查询时c = a + b;
约束
介绍
概念:约束是作用于表中字段上的规则,用于限制存储在表中的数据。
目的:保证数据库中数据的正确、有效性和完整性。
分类
分类:
约束 | 描述 | 关键字 |
---|---|---|
非空约束 | 限制该字段的数据不能为null | NOT NULL |
唯一约束 | 保证该字段的所有数据都是唯一、不重复的 | UNIQUE |
主键约束 | 主键是一行数据的唯一标识,要求非空且唯一 | PRIMARY KEY |
默认约束 | 保存数据时,如果未指定该字段的值,则采用默认值 | DEFAULT |
检查约束 | 保证字段值满足某一个条件 | CHECK |
外键约束 | 用来让两张表的数据之间建立连接,保证数据的一致性和完整性 | FOREIGN KEY |
示例:
1 | CREATE TABLE tb_user( |
注意:
约束是作用于表中字段上的,可以在创建表/修改表的时候添加约束。