原笔记的目标是掌握建库、建表与常用类型。命令列表有用,但几处知识需要改正:没有指定字符集不意味着一定是utf8;DECIMAL不是浮点数;DATETIME的存储大小不能脱离版本说成固定8字节。
这次用一个完整的学习库,把命令连起来跑。实验环境是Ubuntu中的独立MySQL 8.0.46实例,不是SQLite替代品,也不连接现有业务数据库。安装和连接过程不在本文展开;下面SQL在已经连接的MySQL会话中执行。
1. 先看你连接的是什么,再谈默认值
SELECT VERSION() AS version, @@character_set_server AS server_charset, @@collation_server AS server_collation;本次独立实例显示8.0.46、utf8mb4和utf8mb4_0900_ai_ci。这是本次实例的结果,不是说所有用户的数据库都这样配置。
服务器可以配置默认字符集。建库未指定时继承服务器默认,表未指定时继承数据库默认;已经存在的表或列还可能有自己的设置。因此教程写“默认utf8”时,至少要说明版本和实际设置。见服务器字符集说明。
2. 建一个名字明确的测试库
下面名字专供本文学习。在你自己的环境里,先确认没有同名的已有业务库;需要换名时,后面的USE和清理命令同步换名。建库先不用IF NOT EXISTS,防止名字已经存在时悄悄接着操作它。
CREATE DATABASE csdn_basics_20261005 CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; USE csdn_basics_20261005;这份排序规则适用于本篇MySQL8.0环境;更旧版本可能不支持,不能直接照搬版本相关名称。
检查当前选择的库和库定义:
SELECT DATABASE() AS current_database; SHOW CREATE DATABASE csdn_basics_20261005;服务器 └─ csdn_basics_20261005 数据库 └─ learner 表 ├─ id、name、balance 列 └─ 每个学习用户是一行USE只是在当前会话选择默认数据库,不是创建表。重新连接后,应再次明确选库,或使用数据库名.表名。
3. 创建表:给每个字段一个具体用途
CREATE TABLE learner ( id INT PRIMARY KEY, name VARCHAR(20) NOT NULL COMMENT '姓名', age INT NULL COMMENT '未知年龄允许NULL', balance DECIMAL(5,2) NOT NULL COMMENT '学习用金额', registered_at DATETIME(0) NOT NULL ) ENGINE=InnoDB; INSERT INTO learner (id, name, age, balance, registered_at) VALUES (1, '小明', 20, 12.30, '2026-10-05 10:00:00'), (2, 'Ada', NULL, 0.00, '2026-10-05 10:01:00');INT用于整数;VARCHAR(20)中的20是字符上限,不是给任何字符集都分配20字节。NULL表示年龄未知,不是0岁,不是字符串'NULL'。
这个小表没有示范把密码明文存在VARCHAR里;需要认证信息时,应另行设计密码哈希与访问控制,字段类型本身不解决安全问题。
检查结构和数据是两件事:
SHOW TABLES; DESCRIBE learner; SHOW CREATE TABLE learner;SHOW TABLES列出表名;DESCRIBE看字段、类型、可空性等;SHOW CREATE TABLE看完整定义。原笔记里的“show 表”不是可直接执行的查表SQL。
这张旧图用于理解Field、Type、Null、Key等表头。它的users表、int显示宽度和字段设置不能当成本篇新表的定义。原文另外三张截图本轮无法读到有效内容,不继续把占位图留作实验依据。
4. 查数据:未知值不要变成一个虚构的0
SELECT id, name, age, balance, registered_at FROM learner ORDER BY id;| id | name | age | balance | registered_at |
|---|---|---|---|---|
| 1 | 小明 | 20 | 12.30 | 2026-10-05 10:00:00 |
| 2 | Ada | NULL | 0.00 | 2026-10-05 10:01:00 |
客户端可能用不同样式显示NULL,但字段语义不变。验证结果时还要看列名、类型与行数,不只是截图中是否出现“小明”。
5. 金额与字符:类型表不如一个对照结果
DECIMAL(M,D)是精确数值类型:M为总有效数字位数,D为小数位数。DECIMAL(5,2)可表示-999.99到999.99,不是“5位整数再加2位小数”,也不是双精度浮点。金额是否适合这范围,要由业务决定。
SELECT CAST('0.10' AS DECIMAL(5,2)) + CAST('0.20' AS DECIMAL(5,2)) AS exact_sum;这次输出0.30。这里只验证精确数值表达式,不能用显示出来的某次小数结果证明FLOAT/DOUBLE与DECIMAL等价。见DECIMAL官方说明。
再比较字符数和字节数:
SELECT id, CHAR_LENGTH(name) AS characters, LENGTH(name) AS bytes FROM learner ORDER BY id; SELECT CHAR_LENGTH(CHAR(0xF0A0808B USING utf8mb4)) AS characters, LENGTH(CHAR(0xF0A0808B USING utf8mb4)) AS bytes;小明为2个字符、6字节,Ada为3个字符、3字节。第二个查询构造一个U+2000B汉字,结果1个字符、4字节,展示utf8mb4可以表示需要四字节的字符,不依赖浏览器是否有它的字体。
VARCHAR的长度上限与整行字节限制是不同层次的问题,不能把“最大65535字节”写成任何字符集下都能定义VARCHAR(65535)。
6. 类型大小要标版本,不能用旧表当万能答案
本篇版本下可先记用途,再查实际存储规则:
| 类型 | 主要用途 | 容易混淆的点 |
|---|---|---|
| INT、BIGINT | 整数 | SIGNED与UNSIGNED范围不同;Java映射还受驱动和读取API影响 |
| DECIMAL | 精确小数 | 按十进制位分组存储,不能用“M/D最大值+2”算字节 |
| FLOAT、DOUBLE | 近似数值 | 不是金额精确计算的同义词 |
| VARCHAR | 变长文本 | 声明字符上限,存储另计字节与长度信息 |
| BLOB | 二进制数据 | 不应简单当作带字符集的长文本 |
| DATETIME | 日期时间值 | 本篇DATETIME(0)的普通部分5字节;不自动做TIMESTAMP式时区转换 |
| TIMESTAMP | 带会话时区转换的时间戳 | 存取会涉及会话时区,范围与小数秒也要核对版本 |
DATETIME在MySQL5.6.4以前的格式为8字节;较新的格式普通部分5字节,小数秒另加0至3字节。这个结论来自官方存储规则,本文没有做物理页或表文件大小测量。
时区行为也不能靠这个没有TIMESTAMP列的小表验证;需要相关字段时,另做改变session time_zone的对照。这里避免为了“完整”把所有类型堆成一张没有验证边界的大表。
7. 清理不是撤销按钮
完成实验、核对当前库并确认确实是刚才的测试对象后,才执行下面清理。DROP删除对象及其数据,不是普通查询,也不要拿事务回滚当保底。
DROP TABLE csdn_basics_20261005.learner; DROP DATABASE csdn_basics_20261005;用完整限定名减少选错当前库的风险,但它仍不能替你判断对象是否重要。重要数据应先确认备份与恢复方案。
8. 这次如何验证?
验证脚本从文章提取实际SQL块,在新数据目录启动现有MySQL8.0.46二进制,仅使用本地socket且关闭网络监听。本文SQL按顺序在同一会话执行,检查版本与配置、库和表定义、两行数据、金额结果、字符/字节结果,最后确认测试库确实删除。
另用原文“show 表”的写法测试语法错误,并确认重复建库会报错而不是悄悄复用。它不是生产实例,没有安装或替换系统数据库服务;实例在finally关闭,日志与验证报告保留。
这比只记“建库、建表、删表”多了一步:知道自己连接了什么、创建了什么、看到的结果是什么意思,以及最后到底删掉了什么。