数据表与数据类型
数据库建好了,但数据不能直接扔进"库"里——真正装数据的是表(Table)。表就像 Excel 里的一张工作表:有列(字段),有行(记录)。而每一列存什么类型的数据(数字?文字?日期?),就由数据类型决定。本节先学会挑选数据类型,再动手把
school库的四张表建出来。
📖 本节导读
- 认识最常用的数据类型:整数、小数、字符串、日期时间,以及选型的经验法则
- 掌握
CREATE TABLE建表语法,创建全书通用的 class、student、course、score 四张表 - 学会查看表:
DESC、SHOW TABLES、SHOW CREATE TABLE - 学会修改和删除表:
ALTER TABLE、DROP TABLE
一、常用数据类型
给每一列选类型,就像给行李选箱子:太小装不下,太大浪费空间。下面是日常开发中 90% 场景会用到的类型。
1.1 整数类型
| 类型 | 占用空间 | 取值范围(有符号) | 典型用途 |
|---|---|---|---|
TINYINT | 1 字节 | -128 ~ 127 | 年龄、状态值(0/1) |
INT | 4 字节 | 约 ±21 亿 | 最常用:编号、数量 |
BIGINT | 8 字节 | 约 ±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 日期时间类型
| 类型 | 格式 | 说明 |
|---|---|---|
DATE | 2005-03-15 | 只有日期,适合生日 |
DATETIME | 2026-07-26 10:30:00 | 日期 + 时间,范围 1000 ~ 9999 年 |
TIMESTAMP | 2026-07-26 10:30:00 | 日期 + 时间,会随时区自动转换,范围约 1970 ~ 2038 年,常用于记录数据创建/修改时间 |
1.5 选型经验法则
- 在够用的前提下,选占空间最小的类型(更省磁盘、查询更快)。
- 钱和成绩用
DECIMAL,绝不用FLOAT/DOUBLE。 - 长度不定的文字用
VARCHAR,长度固定的用CHAR,大段文章用TEXT。 - 只需要日期用
DATE;要精确到秒且不怕 2038 年问题就用DATETIME。 - 手机号、身份证号虽然是"数字",但用字符串存——它们不参与计算,且可能以 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:生日只需要年月日,用DATEclass_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_id、score.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 会把表结构和表中所有数据一起删除,不可恢复。请不要对我们刚建好的四张表执行它!
⚠️ 新手常见坑
- 用 FLOAT/DOUBLE 存钱或成绩:会产生精度误差,金额对不上账。精确数值一律
DECIMAL。 - 手机号用 INT 存:手机号 11 位超出 INT 范围(约 21 亿),而且可能以 0 开头的号码会丢 0。用
VARCHAR存。 - 忘记先
USE school;就建表:报No database selected。 - 建表语句最后一列后面多写了逗号:如
class_id INT,后直接),会报语法错误。最后一列后面不要逗号。 - 把
DESC 表名(查看结构)和排序里的DESC(降序)搞混:它们是两个不同场景的关键字,前者是 describe 的缩写,后者是 descending 的缩写。 - 随意 DROP TABLE:数据无法恢复,删前确认表名并考虑备份。
📝 小结
- 数据类型选型口诀:整数用
INT,钱和分数用DECIMAL,短文本VARCHAR、定长CHAR、长文TEXT,生日DATE、时刻DATETIME。 CREATE TABLE 表名 (列名 类型 约束, ...)建表;PRIMARY KEY主键、AUTO_INCREMENT自增、NOT NULL非空、DEFAULT默认值。- 查看类:
DESC 表名、SHOW TABLES、SHOW 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)DATETIME 或 TIMESTAMP——需要精确到秒;(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) 而不用 FLOAT?DECIMAL(5,1) 能表示的最大值是多少?
参考答案
因为 FLOAT 是近似存储,成绩可能出现精度误差;DECIMAL 精确存储。DECIMAL(5,1) 总共 5 位数字、1 位小数,最大值是 9999.9。