MySQL速览
数据库介绍
数据库 (Database) 是一个有组织的相互关联数据的集合, 对现实世界的某些方面进行建模 (例如, 对班级中的学生或数字音乐商店的建模).
人们常常混淆“数据库”和“数据库管理系统”(例如,MySQL、Oracle、MongoDB). 数据库管理系统(DBMS) 是管理数据库的软件.
让我们用一个数字音乐商店的模型作为例子.
为什么要有数据库
不就是存数据吗.
flat file(平面文件), 例如 csv (comma-separated value) 文件
这样存储数据有一些问题:
Data Integrity (数据可靠性)
作者相同怎么处理?
非法字符串覆盖了某一字段怎么处理?
实现
怎么找到一条特定的纪录?
两个线程同时写同一条纪录怎么办?
持久性
存储数据的机器崩了怎么办?
怎么在多台机器上存储副本以保证高可获取性?
专业的事情交给专业的处理.
数据库管理系统
数据库管理系统(DBMS)是一种允许应用程序在数据库中存储和分析信息的软件。
通用的DBMS旨在根据某种数据模型允许定义、创建、查询、更新和管理数据库。
数据模型是用于描述数据库中数据的一组概念。
示例:关系型(最常见)、NoSQL(键值、图形)、数组/矩阵/向量等。
模式是基于数据模型描述特定数据集合的说明。
早期的DBMS
由于逻辑层和物理层之间存在紧密耦合,数据库应用程序的构建和维护很困难。
逻辑层描述数据库具有的实体和属性
物理层则描述这些实体和属性的存储方式
早期,物理层是在应用程序代码中定义的,因此如果我们想要更改应用程序正在使用的物理层,就必须更改所有代码以匹配新的物理层。
关系模型
1970年,Ted Codd 注意到每当人们想要更改物理层时,就会重写数据库管理系统(DBMS),因此他提出了关系模型以避免这种情况。 关系模型基于关系定义了一个数据库抽象,以避免维护开销。它有三个关键要点:
使用简单的数据结构(关系)来存储数据库。
通过高级语言访问数据,DBMS找出最佳执行策略。
物理存储由DBMS实现决定。
关系数据模型定义了三个概念:
结构:关系及其内容的定义。这是关系具有的属性和这些属性可以保存的值。
完整性:确保数据库内容满足约束条件。例如,约束条件可能是年份属性的任何值必须是一个数字。
操作:如何访问和修改数据库的内容。
关系是一个无序集合,包含表示实体的属性关系。由于关系是无序的,DBMS可以以任何希望的方式存储它们,以实现优化。
元组是关系中属性值(也称为其域)的集合。最初,值必须是原子或标量的,但现在值也可以是列表或嵌套的数据结构。每个属性都可以是一个特殊值NULL,这意味着对于给定的元组,该属性未定义。
具有 n 个属性的关系称为 n 元关系。
SQL数据库
关系型数据库把数据存放在表中. 列数在设计表的时候就确定了, 行数则是可变的.
类比: Excel 表格
主键: 表中的唯一标识符
外键: 引用的主键
行之间的这种联系就是关系.
关系型数据库引擎为联结操作提供了必要的支持.
关系代数
回顾: 你肯定学过二元关系.
二元关系不就是一个 pair 的集合
让我们推广下...关系就是一个元组 tuple 的集合
谓词:
为什么通常用 P 开头? 因为是 predicate.
就是一个谓词. 当然你得约束下 的类型.
Select 传入一个关系, 输出关系中满足特定条件元组的子集. (条件筛查)
众所周知谓词可以复合, 所以析取/合取也是没有问题的.
例如
对应SQL语句
Projection 投影
其实就是多个 Select 复合
Union
Intersection
Difference
Product 笛卡尔乘积
其实你也可以写成
Join 会把两个关系连接到一起, 生成一个新的关系. 怎么连, 就看两个关系之间存在什么共同性质, 以这些性质为根据, 把相同值的元组关联起来.
比如说学生选课情况, courses
和 enrollment
都存有课程的名称, 那么
就可以得到类似于下面的新表
num | name | c_num | students |
---|---|---|---|
CS186 | DB | CS186 | 700 |
CS186 | DB | CS188 | 800 |
CS188 | AI | CS186 | 700 |
CS188 | AI | CS188 | 800 |
CS189 | ML | CS186 | 700 |
CS189 | ML | CS188 | 800 |
下面的其实是 Natural Join. 这个世界上还有 ⟕ ⟖ 和 ⟗
关系代数是一个procedural language(过程化语言)
和
实际上结果是一样的, 但如果 S 中 id
有 10亿条而 id=102
的数据只有一条, 显然第二个查询会快得多.
实际上计算顺序我们会交给DBMS来决定. SQL就是干这个活的. 而怎么设计这个程式, 这又是另一个故事了.
SQL 语法
接下来我们会介绍少部分SQL的语法. 有关这部分, 它将会是下学期各位计科同学的学习内容, 所以可以提前了解下!
检索数据
基础操作: SELECT
所有的 SQL 语句用
;
结尾.SQL 关键字大写, 变量名小写是好习惯.
结果是未排序的.
排序检索: ORDER BY
SQL 语句由子句(clause)构成, 有些子句是必须的, 有些则不是.
ORDER BY
字句
数据过滤: WHERE
通常数据过滤在服务器而不是在客户端解决. 想想为什么?
ORDER BY
得放在WHERE
后面.使用圆括号分组操作符是个好习惯.
MySQL 里的
NOT
和其他 SQL 语句略有不同.NOT IN
,NOT BETWEEN
也支持.
操作符 | 说明 |
---|---|
| 等于 |
| 不等于[^1] |
| 不等于 |
| 小于 |
| 小于等于 |
| 大于 |
| 大于等于 |
| 在指定的两个值之间 |
通配符和 regex
通配符(wildcard)用来匹配值的一部分的特殊字符.
搜索模式(search pattern)由字面值(literal), 通配符或两者组合构成的搜索条件.
通配符就是 WHERE 字句中具有特殊含义的字符.
%
匹配不了NULL
.不要过度使用通配符, 注意通配符位置.
MySQL 只实现 REGEX 里的很小一块子集.
LIKE
和REGEXP
的区别: 完全匹配整个列和部分匹配.
计算字段
字段(field)基本上就是列的意思.
拼接字段得到一个导出列(derived column)
AS
关键字: 别名(alias)
数据处理函数
文本处理函数:
函数名 | 描述 |
---|---|
CONCAT | 用于连接多个字符串 |
UPPER | 将字符串转换为大写 |
LOWER | 将字符串转换为小写 |
SUBSTRING | 从字符串中提取子字符串 |
LENGTH | 返回字符串的长度 |
TRIM | 去除字符串首尾的空格 |
LTRIM | 去除字符串开头的空格 |
RTRIM | 去除字符串末尾的空格 |
LEFT | 返回字符串左边指定长度的子字符串 |
RIGHT | 返回字符串右边指定长度的子字符串 |
REPLACE | 替换字符串中的指定子字符串 |
CHARINDEX | 返回指定子字符串在字符串中第一次出现的位置 |
REVERSE | 反转字符串 |
FORMAT | 将数值或日期格式化为指定的字符串表示 |
COALESCE | 返回第一个非空表达式的值 |
CASE | 条件语句,用于在结果中根据条件返回不同的值 |
REGEXP_REPLACE | 使用正则表达式替换字符串中的内容 |
TRANSLATE | 替换字符串中的指定字符 |
SOUNDEX | 返回字符串的 SOUNDEX 码,用于模糊匹配字符串的发音 |
CONCAT_WS | 用指定的分隔符连接多个字符串,并去除空字符串 |
INITCAP | 将字符串的首字母大写 |
STRPOS | 返回指定子字符串在字符串中第一次出现的位置 |
LEFTPAD | 在字符串的左侧填充指定字符 |
RIGHTPAD | 在字符串的右侧填充指定字符 |
日期函数:
函数名 | 说明 |
---|---|
AddDate | 增加一个日期(天、周等) |
AddTime | 增加一个时间(时、分等) |
CurDate | 返回当前日期 |
CurTime | 返回当前时间 |
Date | 返回日期时间的日期部分 |
DateDiff | 计算两个日期之差 |
Date_Add | 高度灵活的日期运算函数 |
Date_Format | 返回一个格式化的日期或时间串 |
Day | 返回一个日期的天数部分 |
DayOfWeek | 对于一个日期,返回对应的星期几 |
Hour | 返回一个时间的小时部分 |
Minute | 返回一个时间的分钟部分 |
Month | 返回一个日期的月份部分 |
Now | 返回当前日期和时间 |
Second | 返回一个时间的秒部分 |
Time | 返回一个日期时间的时间部分 |
Year | 返回一个日期的年份部分 |
不同的 DBMS 对函数的实现和语法有些区别. 这么多谁记得住. 建议看文档.
汇总数据: 聚集函数
汇总数据严格来说不是检索数据.
聚集函数(aggregate function): 运行在行组上, 计算和返回单个值的函数.
COUNT(*)
: 行的值为空依然计数COUNT(column)
: column 有值的计数MAX()
要求指定列名ALL
默认DISTINCT
只包含不同的值可以组合聚集函数.
聚合函数:
函数名 | 说明 |
---|---|
AVG() | 返回某列的平均值 |
COUNT() | 返回某列的行数 |
MAX() | 返回某列的最大值 |
MIN() | 返回某列的最小值 |
SUM() | 返回某列值之和 |
分组数据: GROUP BY 和 HAVING
GROUP BY
(创建分组) 和HAVING
(过滤分组)GROUP BY
支持多级分组. 数据将在最后规定的分组上进行汇总.GROUP BY
在WHERE
后,ORDER BY
前WHERE
过滤行, 而HAVING
过滤分组(两者很相似, 操作符通用)可以这么想:
WHERE
在分组前过滤,HAVING
在分组后过滤.而且
HAVING
可以和WHERE
混着用
ORDER BY | GROUP BY | |
---|---|---|
输出 | 按指定列排序的结果 | 分组后的结果,但输出可能不按照分组的顺序 |
列的使用 | 任意列,甚至非选择的列也可以使用 | 只能使用选择列或表达式列,必须使用每个选择列表达式 |
必要性 | 不一定需要 | 如果与聚集函数一起使用列(或表达式),则必须使用 |
在SQL查询中, SELECT
子句的一般顺序如下:
SELECT
:指定要检索的列或表达式。FROM
:指定要从中检索数据的表或视图。WHERE
:应用条件来筛选满足特定条件的行。GROUP BY
:根据指定的列或表达式对结果进行分组。HAVING
:筛选分组后的结果集。ORDER BY
:指定结果集的排序顺序。LIMIT
/OFFSET
(在某些数据库中可用):限制返回的行数或指定结果集的偏移量。
使用子查询
子查询(subquery): 查找一遍又一遍
子查询总是从内向外处理.
相关子查询(correlated subquery): 涉及外部查询的子查询.
逐渐增加子查询来建立查询. 也就是先分成多部查询, 确定正常后再写进子查询.
最后更新于