跳到主要内容

2.2 数据表与数据类型

数据库建好了,但数据不能直接扔进"库"里——真正装数据的是(Table)。表就像 Excel 里的一张工作表:有列(字段),有行(记录)。而每一列存什么类型的数据(数字?文字?日期?),就由数据类型决定。本节先学会挑选数据类型,再动手把 school 库的四张表建出来。

📖 本节导读

  • 认识最常用的数据类型:整数、小数、字符串、日期时间,以及选型的经验法则
  • 掌握 CREATE TABLE 建表语法,创建全书通用的 class、student、course、score 四张表
  • 学会查看表:DESCSHOW TABLESSHOW CREATE TABLE
  • 学会修改和删除表:ALTER TABLEDROP TABLE

一、常用数据类型

给每一列选类型,就像给行李选箱子:太小装不下,太大浪费空间。下面是日常开发中 90% 场景会用到的类型。

1.1 整数类型

类型占用空间取值范围(有符号)典型用途
TINYINT1 字节-128 ~ 127年龄、状态值(0/1)
INT4 字节约 ±21 亿最常用:编号、数量
BIGINT8 字节约 ±922 亿亿超大编号(如订单号、用户量过亿的主键)

经验:不确定就用 INT;确定数值很小(如年龄)用 TINYINT 省空间;可能超过 21 亿(如大平台的流水号)用 BIGINT

1.2 小数类型:DECIMAL 与 FLOAT/DOUBLE 的区别

类型特点
FLOAT / DOUBLE近似值存储,可能有微小误差(比如 0.1 + 0.2 算出 0.30000000000000004)
DECIMAL(M,D)精确值存储,M 是总位数,D 是小数位数

FLOAT/DOUBLE 就像用尺子量身高——差个零点几毫米无所谓;DECIMAL 则像银行点钞机——一分钱都不能错。

铁律:钱、成绩等要求精确的数值,一律用 DECIMAL。 例如:

  • DECIMAL(10,2):最多 10 位数字,其中 2 位小数,适合金额(最大 99999999.99)
  • DECIMAL(5,1):最多 5 位数字,1 位小数,适合百分制成绩(如 88.5)——我们的 score 表就用它

1.3 字符串类型:VARCHAR、CHAR、TEXT

类型特点典型用途
CHAR(n)定长,不够 n 个字符就用空格补齐,存取略快长度固定的值:性别、身份证号、手机号
VARCHAR(n)变长,用多少存多少(最多 n 个字符),最常用姓名、标题、邮箱等长度不定的文本
TEXT存大段文本(最大约 6.5 万字符)文章内容、评论、简介

类比:CHAR(10) 像固定 10 个格子的信封——写"张三"两个字,剩下 8 格空着也占地方;VARCHAR(10) 像可伸缩的袋子——装多少占多少。

注意:VARCHAR(50) 的 50 指的是字符数而不是字节数,存 50 个汉字没问题。

1.4 日期时间类型

类型格式说明
DATE2005-03-15只有日期,适合生日
DATETIME2026-07-26 10:30:00日期 + 时间,范围 1000 ~ 9999 年
TIMESTAMP2026-07-26 10:30:00日期 + 时间,会随时区自动转换,范围约 1970 ~ 2038 年,常用于记录数据创建/修改时间

1.5 选型经验法则

  1. 在够用的前提下,选占空间最小的类型(更省磁盘、查询更快)。
  2. 钱和成绩用 DECIMAL,绝不用 FLOAT/DOUBLE
  3. 长度不定的文字用 VARCHAR,长度固定的用 CHAR,大段文章用 TEXT
  4. 只需要日期用 DATE;要精确到秒且不怕 2038 年问题就用 DATETIME
  5. 手机号、身份证号虽然是"数字",但用字符串存——它们不参与计算,且可能以 0 开头。

二、创建表:CREATE TABLE

2.1 基本语法

CREATE TABLE 表名 (
列名1 数据类型 [约束],
列名2 数据类型 [约束],
...
);

方括号 [] 表示可选。先认识三个最常见的"约束"(对列的额外要求,详细讲解见第 04 章):

  • PRIMARY KEY主键,一行数据的唯一身份证,不能重复、不能为空
  • AUTO_INCREMENT自动增长,插入数据时不用手动填,MySQL 自动 1、2、3……往上加,通常配合主键使用
  • NOT NULL:该列不允许为空,插入时必须给值
  • DEFAULT 值默认值,插入时没给这一列时自动填上该值

2.2 创建 school 库的四张表

先确保在 school 库中:

USE school;

① 班级表 class(记录有哪些班级):

CREATE TABLE class (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL
);

② 学生表 student(记录学生信息,class_id 表示所属班级的编号):

CREATE TABLE student (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
gender CHAR(1) DEFAULT '男',
birthday DATE,
class_id INT
);

逐行解读一下 student 表:

  • id INT PRIMARY KEY AUTO_INCREMENT:学号,整数主键,自动从 1 开始编号
  • name VARCHAR(50) NOT NULL:姓名,变长字符串,必填
  • gender CHAR(1) DEFAULT '男':性别只有一个字符('男'/'女'),长度固定所以用 CHAR(1);不填时默认为 '男'
  • birthday DATE:生日只需要年月日,用 DATE
  • class_id INT:班级编号,对应 class 表的 id(这种"表之间的关联"以后讲外键和连接查询时会大显身手)

③ 课程表 course

CREATE TABLE course (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
teacher VARCHAR(50)
);

④ 成绩表 score(哪个学生的哪门课考了多少分):

CREATE TABLE score (
id INT PRIMARY KEY AUTO_INCREMENT,
student_id INT NOT NULL,
course_id INT NOT NULL,
score DECIMAL(5,1)
);

成绩用 DECIMAL(5,1):最多 5 位数字、1 位小数,能精确表示 88.5 这样的分数。

💡 这里的建表是"简化版"——student.class_idscore.student_id 等列其实应该加上外键约束来保证关联的正确性,这部分留到第 04 章《约束》详细讲解。

2.3 查看表结构:DESC

DESC(describe,描述)可以查看一张表有哪些列、什么类型:

DESC student;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(50) | NO | | NULL | |
| gender | char(1) | YES | | 男 | |
| birthday | date | YES | | NULL | |
| class_id | int | YES | | NULL | |
+----------+-------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

各列含义:Field 列名、Type 类型、Null 是否允许为空、Key 键(PRI 表示主键)、Default 默认值、Extra 额外属性。

2.4 查看当前库中的所有表:SHOW TABLES

SHOW TABLES;
+------------------+
| Tables_in_school |
+------------------+
| class |
| course |
| score |
| student |
+------------------+
4 rows in set (0.00 sec)

四张表都建好了。

2.5 查看建表语句:SHOW CREATE TABLE

SHOW CREATE TABLE class;
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| class | CREATE TABLE `class` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

可以看到 MySQL 补全了很多默认信息:存储引擎 InnoDB、字符集 utf8mb4(继承自 school 库的默认设置)。

三、修改表:ALTER TABLE

表建好后发现少了列、类型不合适?用 ALTER TABLE 修改。下面以给 student 表做实验为例(做完我们会改回来)。

① 加列(ADD)——给学生表加一个电话列:

ALTER TABLE student ADD phone VARCHAR(20);

② 改列类型(MODIFY)——把 phone 改成 VARCHAR(30):

ALTER TABLE student MODIFY phone VARCHAR(30);

③ 改列名 + 类型(CHANGE)——把 phone 改名为 tel:

ALTER TABLE student CHANGE phone tel VARCHAR(30);

④ 删列(DROP)——把实验用的 tel 列删掉,恢复原样:

ALTER TABLE student DROP tel;

另外,改表名用:

ALTER TABLE 旧表名 RENAME TO 新表名;

记忆:ADD 加、MODIFY 只改类型、CHANGE 连名字一起改、DROP 删。删列会连同该列的数据一起删除,操作前想清楚。

四、删除表:DROP TABLE

DROP TABLE 表名;
DROP TABLE IF EXISTS 表名; -- 表不存在时不报错

DROP DATABASE 一样,DROP TABLE 会把表结构和表中所有数据一起删除,不可恢复。请不要对我们刚建好的四张表执行它!

⚠️ 新手常见坑

  1. 用 FLOAT/DOUBLE 存钱或成绩:会产生精度误差,金额对不上账。精确数值一律 DECIMAL
  2. 手机号用 INT 存:手机号 11 位超出 INT 范围(约 21 亿),而且可能以 0 开头的号码会丢 0。用 VARCHAR 存。
  3. 忘记先 USE school; 就建表:报 No database selected
  4. 建表语句最后一列后面多写了逗号:如 class_id INT, 后直接 ),会报语法错误。最后一列后面不要逗号。
  5. DESC 表名(查看结构)和排序里的 DESC(降序)搞混:它们是两个不同场景的关键字,前者是 describe 的缩写,后者是 descending 的缩写。
  6. 随意 DROP TABLE:数据无法恢复,删前确认表名并考虑备份。

📝 小结

  • 数据类型选型口诀:整数用 INT,钱和分数用 DECIMAL,短文本 VARCHAR、定长 CHAR、长文 TEXT,生日 DATE、时刻 DATETIME
  • CREATE TABLE 表名 (列名 类型 约束, ...) 建表;PRIMARY KEY 主键、AUTO_INCREMENT 自增、NOT NULL 非空、DEFAULT 默认值。
  • 查看类:DESC 表名SHOW TABLESSHOW CREATE TABLE 表名
  • 修改类:ALTER TABLE ... ADD / MODIFY / CHANGE / DROP / RENAME TO
  • 删除表:DROP TABLE,危险且不可恢复。
  • 本节已建好 class、student、course、score 四张表,下一节往里面插入数据。

✍️ 练习题

1. 以下几列分别应该选什么数据类型?(a)商品价格(b)用户昵称(c)注册时间(d)身份证号

参考答案

(a)DECIMAL(10,2)——金额必须精确;(b)VARCHAR(50)——长度不定的文本;(c)DATETIMETIMESTAMP——需要精确到秒;(d)CHAR(18)——长度固定 18 位,且不参与计算所以用字符串。

2. 写出创建表 teacher 的语句:id 整数主键自增,name 变长字符串最长 50 必填,hire_date 日期。

参考答案
CREATE TABLE teacher (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
hire_date DATE
);

3. 给上题的 teacher 表加一列 salary DECIMAL(10,2),然后再把它删掉。

参考答案
ALTER TABLE teacher ADD salary DECIMAL(10,2);
ALTER TABLE teacher DROP salary;

4. 判断题:VARCHAR(50) 表示最多存 50 个字节,所以只能存 16 个汉字。

参考答案

错。VARCHAR(50) 的 50 是字符数,可以存 50 个汉字(在 utf8mb4 下 MySQL 会自动按需分配字节)。

5. 为什么 score 表的 score 列用 DECIMAL(5,1) 而不用 FLOATDECIMAL(5,1) 能表示的最大值是多少?

参考答案

因为 FLOAT 是近似存储,成绩可能出现精度误差;DECIMAL 精确存储。DECIMAL(5,1) 总共 5 位数字、1 位小数,最大值是 9999.9。