ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

MySQL基础:从建库到查表,先把字符集、金额和NULL用对

2026/10/6 1:51:08 拓冰建站 浏览量
MySQL基础:从建库到查表,先把字符集、金额和NULL用对 原笔记的目标是掌握建库、建表与常用类型。命令列表有用但几处知识需要改正没有指定字符集不意味着一定是utf8DECIMAL不是浮点数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 ) ENGINEInnoDB; 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. 查数据未知值不要变成一个虚构的0SELECT id, name, age, balance, registered_at FROM learner ORDER BY id;idnameagebalanceregistered_at1小明2012.302026-10-05 10:00:002AdaNULL0.002026-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字节。第二个查询构造一个U2000B汉字结果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关闭日志与验证报告保留。这比只记“建库、建表、删表”多了一步知道自己连接了什么、创建了什么、看到的结果是什么意思以及最后到底删掉了什么。