# SQL语法
SQL(Structured Query Language)即结构化查询语言,它是数据库的标准语言。SQL 非常简洁,它只有 6 个常用动词:insert(增)、delete(删)、select(查)、update(改)、create(创建)和 grant(授权)。
# SQL 简介
SQL 可以分为三大类:1.数据定义语言,2.数据操纵语言,3.数据控制语言。
1.数据定义语言
数据定义语言(Data Definition Language,DDL)主要用于对数据表进行创建、删除或修改等操作。其中数据定义语句有 3 种,如表 2-1 所示。
表 2-1 数据定义语句
语句 | 说明 |
---|---|
create table | 创建表 |
drop table | 删除表 |
alter table | 修改表 |
2.数据操纵语言
数据操纵语言(Data Manipulation Language,DML)主要用于对数据进行增删查改操作。其中数据操纵语句有 4 种,如表 2-2 所示。
表 2-2 数据操纵语句
语句 | 说明 |
---|---|
insert | 增加数据 |
delete | 删除数据 |
select | 查询数据 |
update | 更新数据 |
3.数据控制语言
数据控制语言(Data Control Language,DCL)主要用于对数据库和表的权限进行管理。其中数据控制语句有两种,如表 2-3 所示。
表 2-3 数据控制语句
语句 | 说明 |
---|---|
grant | 赋予用户权限 |
revoke | 取消用户权限 |
# 关键字
关键字指的是 SQL 本身“已经在使用”的单词或词组,因此在给数据库、表、列等命名时是不能使用这些单词或词组的(因为 SQL 自己要用)。
常见的关键字有:select、from、where、group by、order by、distinct、like、insert、delete、update、create table、alter、drop、is not、inner join、left outer join、right outer join、procedure、function 等。
对于这些关键字,小伙伴们不需要刻意去记忆。
# 语法规则
SQL 本身是一门编程语言,所以它有自己的语法规则。不过 SQL 的语法规则非常简单,我们只需要清楚以下两点即可。
1.不区分大小写
对于表名、列名、关键字等,SQL 是不区分大小写的。比如 select 这个关键字,写成 select、SELECT 或 Select 都是可以的。下面两种写法是等价的。
-- 写法 1 :关键字小写
select * from student;
-- 写法 2 :关键字大写
SELECT * FROM student;
2
3
4
5
对于大小写,这里要重点说明的是,很多书都推荐使用写法 2,也就是关键字一律大写。其实对于使用中文环境的人来说,大写的关键字阅读起来是非常不直观的。因此,对于初学者来说,我们更推荐小写。
SQL 语句应该以分号结尾
如果执行一条 SQL 语句,则它的结尾加不加英文分号(;)都是可行的。但是如果同时执行多条 SQL 语句,则每一条语句的后面都必须加上英文分号才行。
-- 方式 1 :加分号
select * from student;
-- 方式 2 :不加分号
select * from student
2
3
4
5
中文的一句话需要用一个句号(。)来表示结束。一条 SQL 语句相当于 SQL 中的一句话,所以为了代码规范,不管是一条 SQL 语句,还是多条 SQL 语句,建议都加上英文分号。
# 命名规则
命名规则主要是针对数据库、表、列的。对于数据库、表、列的命名,需要遵循以下两条规则。
1.不能是 SQL 关键字
前面讲过,关键字指的是 SQL 本身“已经在使用”的单词或词组,因此我们在给数据库、表、列等命名时,是不能使用这些单词或词组的(因为 SQL 自己要用)。比如 select、delete、from 等都是 SQL 中的关键字。
2.只能使用英文字母、数字、下划线(_)
在给数据库、表、列等命名时,只能使用英文字母(大小写都可以)、数字、下划线(_)这 3 种字符,而不能使用其他符号,如中划线(-)、美元符号($)等。
-- 正确命名
fruit_name
-- 错误命名
fruit-name
2
3
4
5
如果小伙伴们接触过其他编程语言(如 C 语言、Java、Python 等),那么应该知道每一门编程语言都有它自己的数据类型。SQL 本身也是一门编程语言,所以它也有自己的数据类型。
由于本书使用的是 MySQL,所以只介绍 MySQL 中的数据类型。其他 DBMS(如 SQL Server、Oracle、PostgreSQL 等)的数据类型也是大同小异,小伙伴们可以自行了解。
# 数据类型
MySQL 的数据类型主要有以下四大类。
- 数值。
- 字符串。
- 日期时间。
- 二进制。
# 数值
数值可以分为三大类:①整数,②浮点数,③定点数。MySQL 中的整数类型有 5 种,如表 2-4 所示。在实际开发中,大多数情况下使用 int 类型。
表 2-4 整数
类型 | 说明 | 取值范围 |
---|---|---|
tinyint | 很小的整数 | -27~27-1(-128~127) |
smallint | 小的整数 | -215~215-1(-32768~32767) |
mediumint | 中等的整数 | -223~223-1 |
int(或 integer) | 普通的整数 | -231~231-1 |
bigint | 大整数 | -263~263-1 |
选择哪一种整数类型取决于对应列的数值范围,如果对应列的最大值不超过 127,那么选择 tinyint 类型就足够了。选择取值范围过大的类型,需要占据更大的空间。
浮点数类型有两种,如表 2-5 所示。需要注意的是,浮点数类型存在精度损失,比如 float 类型的浮点数只保留 7 位有效位,会对最后一位数进行四舍五入。
表 2-5 浮点数
类型 | 说明 | 有效位 |
---|---|---|
float | 单精度 | 7 位 |
double | 双精度 | 15 位 |
定点数只有一种,如表 2-6 所示。和浮点数不一样,定点数不存在精度损失,所以大多数情况下建议使用定点数来表示包含小数的数值。特别是银行存款这种数值,如果用浮点数来表示就会非常麻烦。
表 2-6 定点数
类型 | 说明 | 有效位 |
---|---|---|
decimal(m, d) | 定点数 | 取决于 m 和 d |
decimal(m, d) 的 m 表示该数值最多包含的有效数字的个数,d 表示有多少位小数。
举个简单的例子,decimal(10, 2) 中的“2”表示小数部分的位数为 2,如果插入的数值没有小数或者小数不足两位,就会自动补全到两位(补 0)。如果插入的数值的小数超过了两位,那么就会直接截断多余位(不会四舍五入),最后保留两位。decimal(10, 2) 中的“10”指的是整数部分加小数部分的总位数,也就是说,整数部分不能超过 8 位(10-2),否则就无法插入成功,并且会报错。
此外,decimal(m, d) 中的 m 和 d 都是可选的,m 的默认值是 10,d 的默认值是 0。因此可以得出下面的等式。
decimal = decimal(10, 0)
MySQL 是不存在布尔类型(Boolean)的。但是在实际开发过程中,经常需要用到“是”和“否”以及“有”和“无”这种数据,这应该怎么表示呢?我们可以使用 tinyint(1)、tinyint(0) 这种方式来表示,其中“1”表示 true,“0”表示 false。
# 字符串
字符串其实就是一串字符。在 MySQL 中,字符串都是使用英文单引号或英文双引号引起来的。MySQL 中常用的字符串类型有 7 种,如表 2-7 所示。
表 2-7 字符串类型
类型 | 说明 | 字节 |
---|---|---|
char | 定长字符串 | 0~255(28-1) |
varchar | 变长字符串 | 0~65535(216-1) |
tinytext | 短文本 | 0~255(28-1) |
text | 普通长度文本 | 0~65535(216-1) |
mediumtext | 中等长度文本 | 0~16777215(224-1) |
longtext | 长文本 | 0~4294967295(232-1) |
enum | 枚举类型 | 取决于成员个数(最多 64 个) |
在实际开发中,最常用的是 char、varchar、text、enum 这 4 种类型,所以接下来会重点介绍它们。
# char
在 MySQL 中,可以使用 char 类型来表示一个“固定长度”的字符串。
语法:
char(n)
说明:
n 表示指定的长度,它是一个整数,取值范围为 0~255。比如 char(5) 表示字符串长度为 5,也就是说,包含的字符个数最多为 5。如果字符串的长度不足 5,那么就在其右边填充空格。如果字符串的长度超过 5 就会报错,此时字符串将无法存入数据库。char(5) 的存储情况如表 2-8 所示。
表 2-8 char(5)
插入值 | 存储值 | 占用空间 |
---|---|---|
'' | ' ' | 5 个字节 |
'a' | 'a ' | 5 个字节 |
'ab' | 'ab ' | 5 个字节 |
'abcde' | 'abcde' | 5 个字节 |
'abcdef' | 无法存入 | 无法存入 |
# varchar
在 MySQL 中,可以使用 varchar 类型来表示一个“可变长度”的字符串。
语法:
varchar(n)
说明:
n 表示指定的长度,它是一个整数,取值范围为 0~65535。和 char 不一样,varchar 的占用空间是由字符串的实际长度来决定的。varchar(5) 的存储情况如表 2-9 所示。
表 2-9 varchar(5)
插入值 | 存储值 | 占用空间 |
---|---|---|
'' | '' | 1 个字节 |
'a' | 'a' | 2 个字节 |
'ab' | 'ab' | 3 个字节 |
'abcde' | 'abcde' | 6 个字节 |
'abcdef' | 无法存入 | 无法存入 |
需要特别注意的是,varchar 实际占用的空间等于“字符串的实际长度”再加上 1,因为它在存储字符串时会在字符串末尾加上一个结束字符。
虽然 varchar 使用起来比较灵活,并且可以节省存储空间;但是从性能上来看,char 的处理速度更快。因此在设计数据库时,应该综合考虑多方面的因素来选取合适的数据类型存储数据。
从字面上也可以看出来,varchar 指的是“variable char”。其中,char 和 varchar 之间的区别如下。
- char 也叫作“定长字符串”,它的长度是固定的,存储相同数据时占用的空间大,但是性能稍高。
- varchar 也叫作“变长字符串”,它的长度是可变的,存储相同数据时占用的空间小,但是性能稍低。
# text
如果要存储一个超长字符串(如文章内容),此时就更适合使用 text 这种类型了。text 其实相当于 varchar(65535),它本质上也是一个“变长字符串”。
与 text 类型相关的类型还有 tinytext、mediumtext、longtext,如表 2-10 所示。它们都是“变长字符串”,唯一的区别在于可存储的长度不同。
表 2-10 text 的相关类型
类型 | 说明 | 字节 |
---|---|---|
tinytext | 短文本 | 0~255(28-1) |
mediumtext | 中等长度文本 | 0~16777215(224-1) |
longtext | 长文本 | 0~4294967295(232-1) |
# enum
在实际开发中,有些变量只有几种可能的取值。比如人的性别只有两种值:男和女。星期只有 7 种值:1、2、3、4、5、6、7。
在 MySQL 中,可以将某个字段定义为 enum 类型(枚举类型),然后限定该字段在某个范围内取值。
比如,某个字段使用 enum 类型定义了一个枚举列表:'first', 'second', 'third',那么该字段可以取的值和每个值的索引如表 2-11 所示。
# 日期时间
日期时间主要用于表示“日期(年月日)”和“时间(时分秒)”。MySQL 的日期时间类型有 5 种,如表 2-12 所示。
表 2-12 日期时间类型
类型 | 格式 | 说明 | 举例 |
---|---|---|---|
date | YYYY-MM-DD | 日期型 | 2022-01-01 |
time | HH:MM:SS | 时间型 | 08:05:30 |
datetime | YYYY-MM-DD HH:MM:SS | 日期时间型 | 2022-01-01 08:05:30 |
year | YYYY | 年份型 | 2022 |
timestamp | YYYYMMDD HHMMSS | 时间戳型 | 20220101 080530 |
在 MySQL 中输入日期时间数据时,数据必须符合相应的格式才能正确输入。比如类型为 date,那么字段的值必须符合“YYYY-MM-DD”这种格式,而不能是其他格式。
每个类型都有特定的格式以及取值范围,当指定不合法的值时,系统就会将“0”插入数据库中。
如果使用的是 Navicat for MySQL,我们可以使用提示按钮来辅助输入,如图 2-3 所示。如果是在程序中插入数据,就需要特别注意格式了。
图 2-3
1.日期型
日期型(date)的数据格式为:YYYY-MM-DD。其中,YYYY 是年份,MM 是月份,DD 表示某一天。比如 2022 年 1 月 1 日的存储格式应为:2022-01-01。
2.时间型
时间型(time)的数据格式为:HH:MM:SS。其中,HH 表示小时,MM 表示分钟,SS 表示秒。比如 8 时 4 分 30 秒的存储格式应为:08:04:30。
3.日期时间型
日期时间型(datetime)的数据格式为:YYYY-MM-DD HH:MM:SS。其中,YYYY 是年份,MM 是月份,DD 表示某一天,HH 表示小时,MM 表示分钟,SS 表示秒。
比如 2022 年 1 月 1 日 8 时 4 分 30 秒的存储格式应为:2022-01-01 08:04:30。
4.年份型
年份型(year)的数据格式为:YYYY。YYYY 是年份。比如 2022 年的存储格式应为:2022。
5.时间戳型
时间戳型(timestamp)的数据格式为:YYYYMMDD HHMMSS。其中,YYYY 是年份,MM 是月份,DD 表示某一天,HH 表示小时,MM 表示分钟,SS 表示秒。
比如 2022 年 1 月 1 日 8 时 4 分 30 秒的存储格式应为:20220101 080430。
datetime 和 timestamp 都可以用于表示“YYYY-MM-DD HH:MM:SS”格式的日期时间,除了存储方式、存储大小以及表示范围有所不同之外,这两种类型没有太大的区别。一般情况下,datetime 用得较多;而对于跨时区的业务,则使用 timestamp 更为合适。
# 二进制
二进制类型适用于存储图像、有格式的文本(如 Word 文档、Excel 文档等)、程序文件等数据。MySQL 的二进制类型有 5 种,如表 2-13 所示。
表 2-13 二进制类型
类型 | 说明 | 字节 |
---|---|---|
bit | 位 | 0~255(28-1) |
tinyblob | 二进制类型的短文本 | 0~255(28-1) |
blob | 二进制类型的普通文本 | 0~65535(216-1) |
mediumblob | 二进制类型的中文本 | 0~16777215(224-1) |
longblob | 二进制类型的长文本 | 0~4294967295(232-1) |
不过在实际开发中,并不推荐在数据库中存储二进制数据,主要是因为二进制数据往往非常大,占用的存储空间过多,这对数据库的性能会有所影响。
# 注释
在实际开发中,有时需要为 MySQL 语句添加一些注释,以方便自己和别人理解代码。
方式 1(推荐):
-- 注释内容
方式 2:
# 注释内容
方式 3:
/*注释内容*/
MySQL 常用的注释方式有上面 3 种。需要特别注意的是,方式 1 的“--”与“注释内容”之间必须要有一个空格。
如果注释内容只有一行,那么这 3 种方式都是可行的。方式 2 是 MySQL 独有的,SQL Server 等就没有这种方式。而大多数 DBMS(如 MySQL、SQL Server 等)都可以使用方式 1。所以为了统一,对于所有 DBMS 的单行注释内容,建议使用方式 1。
如果注释内容过多且需要多行显示,那么此时推荐使用方式 3(示例如下),大多数 DBMS(包括 MySQL、SQL Server 等)都可以使用这种方式进行多行注释。
/*
注释内容
注释内容
注释内容
*/
2
3
4
5