目录

一、为什么需要数据类型与约束?

二、MySQL 数据类型全览

1. 数值类型:精确 VS 近似

2. 日期时间类型:别让“0000-00-00”出现

3. 字符串类型:CHAR、VARCHAR、TEXT、BLOB

4. JSON 类型:文档与关系共舞

5. 空间类型:GIS 场景

6. 二进制与位类型

三、约束:给数据装上“安检门”

1. 列级约束:NOT NULL、DEFAULT、UNIQUE、CHECK

2. 主键与复合主键

3. 外键:一把双刃剑

4. 表级 CHECK 与触发器

5. 视图与权限:最后一道软性约束

四、联动设计:把类型与约束串成故事

1. 用户表

2. 订单表

3. 支付表

4. 索引与性能

五、最佳实践 5 条

六、结语


一、为什么需要数据类型与约束?

想象你在咖啡馆点单:
“我要一杯拿铁,中杯,加一份浓缩,半糖,少冰。”
如果服务员只在本子上写“拿铁”,结果可能端来超大杯、全糖、冰多到溢出。
数据库同理:字段若不声明“多大”“什么格式”“能否为空”,就会像“拿铁”一样失控——数字被截断、日期变 0000-00-00、字符串乱码、金额出现负值……
数据类型解决“存得对”,约束保证“存得准”。二者共同构成 MySQL 的第一道防线,也是性能与可维护性的根基。

二、MySQL 数据类型全览

1. 数值类型:精确 VS 近似

大类典型字节范围(有符号)场景
整数TINYINT1-128~127性别、布尔
整数INT4-21 亿~21 亿主键、计数器
大整数BIGINT8很大雪花 ID
定点DECIMAL(M,D)变长精确小数金额
浮点FLOAT/DOUBLE4/8近似值温度、GPS

陷阱与建议:

  • 金额永远用 DECIMAL,不要用 DOUBLE。DOUBLE 的二进制浮点误差会让 0.1+0.2≠0.3。

  • 主键自增别用 BIGINT(20)“吓唬”自己,除非预估 9.22e18 行,否则 INT 足够。

  • UNSIGNED 让上限翻倍,但 BIGINT UNSIGNED 与 Java long 互转时会溢出,需在 ORM 层注意。

示例:

CREATE TABLE goods (id        BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,price     DECIMAL(10,2) NOT NULL,stock     INT UNSIGNED DEFAULT 0
);

2. 日期时间类型:别让“0000-00-00”出现

类型字节范围精确度备注
DATE31000-01-01~9999-12-31生日
DATETIME8同上默认无时区
DATETIME(fsp)8+小数同上微秒MySQL 5.6+
TIMESTAMP41970-2038自动时区转换
TIME3-838:59:59~838:59:59时长
YEAR11901-2155几乎不用

陷阱:

  • 旧版本 MySQL 允许 0000-00-00,但 JDBC、Python 驱动会抛异常;务必 sql_mode=NO_ZERO_DATE

  • TIMESTAMP 受时区影响,跨地域系统用 DATETIME+fsp 更稳。

  • 存储毫秒级时间戳可直接用 BIGINT 存 Unix 毫秒,避免 DATETIME 精度不够或 TIMESTAMP 2038 问题。

示例:

CREATE TABLE event_log (id        BIGINT PRIMARY KEY,happen_at DATETIME(3) NOT NULL,INDEX idx_happen (happen_at)
);

3. 字符串类型:CHAR、VARCHAR、TEXT、BLOB

  • CHAR(n) 定长,最大 255,尾部空格自动截断;适合短且等长码值,如国家代码 CHAR(2)

  • VARCHAR(n) 变长,最大 65535 字节,受行大小 65535 限制;utf8mb4 下一个字符 4 字节,所以 VARCHAR(16383) 是极限。

  • TEXT 家族(TINYTEXT、TEXT、MEDIUMTEXT、LONGTEXT)存大文本,不能设默认值,不能完整索引(需前缀索引)。

  • BLOB 家族存二进制,如图片、PDF;同样不能设默认值,读写会走磁盘临时文件,慎用。

陷阱:

  • VARCHAR(255) 不等于 255 字符,而是 255 字节;utf8mb4 下最多 63 个汉字。

  • 用 TEXT 存 JSON 不如直接用 JSON 类型(见下)。

  • 大字段会触发“行溢出”,InnoDB 把值存到页外,随机 IO 增加。

示例:

CREATE TABLE article (id      BIGINT PRIMARY KEY,title   VARCHAR(200) NOT NULL,body    MEDIUMTEXT,cover   LONGBLOB
) CHARSET=utf8mb4;

4. JSON 类型:文档与关系共舞

MySQL 5.7+ 原生 JSON,二进制存储、可部分更新。支持函数 ->->>JSON_EXTRACT()JSON_SET()
优点:schema-less,适合动态字段。缺点:无法直接建外键、无法默认值。
示例:

CREATE TABLE user_ext (user_id BIGINT PRIMARY KEY,profile JSON,CHECK (JSON_VALID(profile))
);-- 查询
SELECT profile->>'$.nickname' AS nick
FROM user_ext
WHERE JSON_CONTAINS(profile->'$.tags', '"vip"');

5. 空间类型:GIS 场景

  • GEOMETRY、POINT、LINESTRING、POLYGON……

  • 需表引擎 InnoDB 或 MyISAM,建 SPATIAL INDEX。

  • 8.0 引入 SRID 强制坐标系,避免“经纬度颠倒”。

示例:

CREATE TABLE shop (id   BIGINT PRIMARY KEY,loc  POINT NOT NULL SRID 4326,SPATIAL INDEX idx_loc (loc)
);

6. 二进制与位类型

  • BINARY/VARBINARY:与 CHAR/VARCHAR 类似,但存字节而非字符,适合存哈希。

  • BIT:最大 64 位,存布尔标志位,省空间但可读性差。

  • ENUM/SET:背后用 1~8 字节存位图,可节省空间,但迁移成本高,不建议滥用。

三、约束:给数据装上“安检门”

1. 列级约束:NOT NULL、DEFAULT、UNIQUE、CHECK

  • NOT NULL:拒绝 NULL;NULL 与任何值比较都未知,导致索引失效。

  • DEFAULT:显式优于隐式;DEFAULT CURRENT_TIMESTAMP 记录创建时间。

  • UNIQUE:允许 NULL,但 NULL≠NULL,因此可出现多条 NULL;8.0.13 前不能有重复 NULL。

  • CHECK:8.0.16 原生支持,之前仅解析忽略;可写表达式 CHECK (age BETWEEN 0 AND 150)

示例:

CREATE TABLE member (id     BIGINT PRIMARY KEY,email  VARCHAR(255) NOT NULL UNIQUE,age    TINYINT CHECK (age BETWEEN 0 AND 150),status ENUM('NEW','VIP','BAN') DEFAULT 'NEW'
);

2. 主键与复合主键

  • 主键 = NOT NULL + UNIQUE;InnoDB 聚簇索引,整张表物理顺序按主键排序。

  • 业务主键 vs 代理主键:自增 BIGINT 简单,但分布式场景用雪花 ID、UUID;后者无序会导致页分裂。

  • 复合主键 (tenant_id, id) 可做分库分表“联合主键”,但所有二级索引都需回表两次。

3. 外键:一把双刃剑

CREATE TABLE orders (id      BIGINT PRIMARY KEY,user_id BIGINT NOT NULL,FOREIGN KEY (user_id) REFERENCES user(id)ON UPDATE CASCADEON DELETE RESTRICT
);

优点:保证引用完整性;缺点:高并发写入时级联更新/删除会锁多表,互联网大厂常关闭外键,靠业务层保证。

4. 表级 CHECK 与触发器

  • 如果 CHECK 表达式复杂(如跨列、跨行),可用 BEFORE INSERT 触发器。

  • 触发器可写业务逻辑,但隐藏、难调试,尽量收敛到“数据校验”而非“业务流程”。

示例:

DELIMITER $$
CREATE TRIGGER trg_order_amount
BEFORE INSERT ON orders
FOR EACH ROW
BEGINIF NEW.amount <= 0 THENSIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'amount must be positive';END IF;
END$$
DELIMITER ;

5. 视图与权限:最后一道软性约束

  • 通过只读视图屏蔽危险列;

  • DEFINERSQL SECURITY INVOKER 做行级安全。

四、联动设计:把类型与约束串成故事

场景:设计“用户-订单-支付”核心表,要求:

  • 用户手机号唯一;

  • 订单金额必须大于 0;

  • 支付记录必须与订单同币种;

  • 支持软删除。

1. 用户表

CREATE TABLE user (id        BIGINT PRIMARY KEY,phone     CHAR(11) NOT NULL UNIQUE,nickname  VARCHAR(50),deleted   TINYINT(1) DEFAULT 0,created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) CHARSET=utf8mb4;

2. 订单表

CREATE TABLE orders (id        BIGINT PRIMARY KEY,user_id   BIGINT NOT NULL,amount    DECIMAL(10,2) NOT NULL CHECK (amount > 0),currency  CHAR(3) DEFAULT 'CNY',status    ENUM('PENDING','PAID','CLOSED') DEFAULT 'PENDING',deleted   TINYINT(1) DEFAULT 0,FOREIGN KEY (user_id) REFERENCES user(id)ON DELETE RESTRICTON UPDATE CASCADE
);

3. 支付表

CREATE TABLE payment (id        BIGINT PRIMARY KEY,order_id  BIGINT NOT NULL,currency  CHAR(3) NOT NULL,pay_amount DECIMAL(10,2) NOT NULL CHECK (pay_amount > 0),paid_at   DATETIME DEFAULT CURRENT_TIMESTAMP,FOREIGN KEY (order_id) REFERENCES orders(id)ON DELETE RESTRICT,CONSTRAINT chk_currency_matchCHECK (currency = (SELECT currency FROM orders WHERE id = order_id))
);

注意:MySQL 8.0.16+ 才支持子查询 CHECK;低版本需触发器实现。

4. 索引与性能

  • 外键会自动创建索引,但 deleted 列需手动加联合索引 (deleted, status) 以便软删除列表查询。

  • DECIMAL 精确字段可用“整数分”代替:存分为 INT,避免浮点运算。

五、最佳实践 5 条

  1. 先选类型,再加约束:类型决定存储空间与运算方式,约束只是“护栏”。

  2. 金额用 DECIMAL(10,2) + CHECK>0;时间用 DATETIME(3) + DEFAULT CURRENT_TIMESTAMP(3)。

  3. 枚举值用 TINYINT 或 VARCHAR 存代码,留扩展空间;ENUM 仅用于非常稳定的状态机。

  4. 外键在 OLTP 关闭,在 OLAP 打开;或只在测试环境打开做 CI。

  5. 上线前跑 pt-oscgh-ost 做无锁变更,防止加约束导致表锁。

六、结语

数据类型与约束是 MySQL 的地基。
类型选错,查询再花哨也如沙上建塔;约束缺失,业务再健壮也靠运气生存。
愿你在每一次 CREATE TABLE 时,都能像挑剔的点单顾客,把“中杯、半糖、少冰”说得清清楚楚,让数据库端出的每一杯“数据拿铁”都刚刚好。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/95666.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/95666.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/95666.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Effective C++ 条款42:了解 typename 的双重含义

Effective C 条款42&#xff1a;了解typename的双重含义 核心思想&#xff1a;在模板声明中&#xff0c;typename和class可互换使用&#xff0c;但在模板内部&#xff0c;typename必须用于显式指明嵌套从属类型名称&#xff08;nested dependent type name&#xff09;&#xf…

ENCOPIM, S.L. 参展 AUTO TECH China 2025 广州国际汽车技术展览会

ENCOPIM, S.L. 参展 AUTO TECH China 2025 广州国际汽车技术展览会2025年11月21-24日中国进出口商品交易会展馆D区(广州)AUTO TECH China 2025同期&#xff1a;第二十三届广州车展即将盛大开幕展商推荐ENCOPIM, S.L.展位号&#xff1a;3916企业简介&#xff1a;ENCOPIM, S.L.于…

30 HTB Soccer 机器 - 容易

主要知识点 第一阶段&#xff1a;侦查 nmap nmap快速扫描&#xff1a; oxdfhacky$ nmap -p- --min-rate 10000 10.10.11.194 Starting Nmap 7.80 ( https://nmap.org ) at 2023-06-04 13:32 EDT Nmap scan report for 10.10.11.194 Host is up (0.093s latency). Not shown:…

阿里云机器翻译接口SDK-RAM权限配置

用户授权翻译权限在数字化时代&#xff0c;短信作为企业与用户沟通的重要桥梁&#xff0c;其高效、可靠的送达直接影响业务转化与用户体验。SDK&#xff08;软件开发工具包&#xff09;的出现极大简化了短信功能的集成过程&#xff0c;让开发者能够快速在应用中嵌入短信验证、通…

ESXI 6.7服务器时间错乱问题

1. 设置ESXI服务器&#xff1a;在此主机上手动配置日期和时间管理-服务-ntpd-鼠标右键-策略-手动启动和停止&#xff0c;状态已停止管理-系统-时间和日期-编辑设置-检查是否选择了【在此主机上手动配置日期和时间】ntp服务状态已停止ntp服务器已停止2. 停止所有虚拟机自动更新时…

CV 医学影像分类、分割、目标检测,之【皮肤病分类】项目拆解

CV 医学影像分类、分割、目标检测&#xff0c;之【皮肤病分类】项目拆解第1-12行&#xff1a;导入库第14-17行&#xff1a;读取标签文件第19-21行&#xff1a;获取疾病名称第23-26行&#xff1a;获取图片名列表第28-35行&#xff1a;筛选有标签的图片第38-43行&#xff1a;提取…

【JavaEE】多线程 -- 线程状态

目录六大状态举例说明六大状态 New 新建状态&#xff1a;线程还没出创建&#xff0c;只有Thread 实例化的对象&#xff0c;调用start 方法之前的状态。Runnable 运行状态&#xff1a;被系统调度后&#xff0c;CPU 正在执行的&#xff0c;Ready 就绪态&#xff0c;系统调度&…

网络流初步

网络流初步 文章目录网络流初步概念介绍最大流费用流概念介绍 网络流不同之处在于它的本质图论&#xff0c;但是把图论的某些概念换了一个说法而已&#xff0c;初步只要了解网络流的各个概念就可以明白的很快。 下述概念是本人自己定义的&#xff0c;对于网络流的题目做的还不…

[系统架构设计师]系统架构基础知识(一)

[系统架构设计师]系统架构基础知识&#xff08;一&#xff09; 一.计算机系统基础知识 1.计算机系统概述 硬件软件及网络组成的系统 2.计算机硬件基础知识 冯 诺依曼结构&#xff1a;运算器&#xff0c;控制器&#xff0c;存储器&#xff0c;输入设备&#xff0c;输出设备 专用…

深入解析Java代理模式:灵活控制对象访问的核心技术

在日常开发中&#xff0c;我们常遇到这样的场景&#xff1a;需要控制对象访问权限、优化高成本操作&#xff0c;或给方法添加额外功能&#xff08;如日志、事务&#xff09;。代理模式&#xff08;Proxy Pattern&#xff09; 正是解决这类问题的金钥匙。作为结构型设计模式的代…

【学习笔记】Java并发编程的艺术——第9章 Java中的线程池

第9章 Java中的线程池 线程池优势&#xff1a; ①减少资源消耗 ②提高响应速度 ③统一管理 9.1 线程池的实现原理 当任务来后 ①判断核心线程池是否已满&#xff0c;若未满&#xff0c;创建一个核心线程来执行任务 ②若无空闲核心线程且核心线程已满&#xff0c;则将任务放入任…

Mybatis学习笔记(九)

常见问题与解决方案 简要描述&#xff1a;总结MyBatis-Plus开发过程中常见的问题、错误及其解决方案&#xff0c;帮助开发者快速定位和解决问题。 核心概念&#xff1a; 常见错误&#xff1a;开发中经常遇到的错误类型性能问题&#xff1a;性能相关问题的排查和解决配置问题&am…

数据类型 list

一、介绍类似于数组&#xff0c;顺序表&#xff0c;deque结构图特点&#xff1a;元素有序&#xff0c;元素允许重复由于头尾高效插入删除&#xff0c;可以模拟栈&#xff0c;队列二、常见 list 命令1、lpush key elem [elem ...]头插元素&#xff0c;返回值列表长度2、lrange k…

pyqt5无法显示opencv绘制文本和掩码信息

背景&#xff1a;pyqt5无法显示opencv绘制的标签和mask&#xff1b;我们在使用YOLO做实例分割做推理时&#xff0c;会使用opencv做后处理结果绘制&#xff08;含标签绘制和掩码绘制&#xff09;&#xff1b;结果opencv绘制的解码却无法在pyqt的解码上面显示。pyqt转换代码如下&…

如何生成严格递增的分布式id?

本文字数&#xff1a;2604字预计阅读时间&#xff1a;15分钟01引言在现有分布式系统中&#xff0c;面对增长迅速的业务数据&#xff0c;id生成一直是非常重要的一环。而分布式系统的id生成方案需要满足几个重要特性&#xff1a;容错高可用、高性能高并发、全局唯一。02技术背景…

【LeetCode】二叉树相关算法题

目录1、二叉树介绍【1】核心概念【2】关键特性2、算法题【1】二叉树的前序遍历【2】二叉树的后序遍历1、二叉树介绍 【1】核心概念 结构含义节点结构二叉树由节点组成&#xff0c; 每个节点包含一个数据元素和最多两个子节点&#xff1a;左子节点和右子节点根节点树的顶部节点…

Vulnhub Deathnote靶机复现攻略

一、靶机安装 下载地址&#xff1a;https://download.vulnhub.com/deathnote/Deathnote.ova 下载好后使用VB打开&#xff0c;配置如下 二、主机发现 使用相同连接方式的kali进行后续操作(172.16.2.7)根据mac地址进行确认。 nmap -sn 172.16.2.1/24 三、端口扫描 端口开放了…

DevEco Studio 6.0.0 元服务页面跳转失败

背景&#xff0c;我使用最新的编辑器DevEco Studio 6.0.0&#xff0c;编写一个元服务&#xff0c;发现使用跳转页面的时候失败了&#xff01;然后查看官方文档&#xff0c;两种方式都测试了&#xff0c;发现都不行。 方法1&#xff1a;Navigation路由跳转无效&#xff0c;见官方…

docker重启或系统重启后harbor自动启动

docker重启或系统重启后harbor自动启动docker重启或系统重启后harbor自动启动方法 1&#xff1a;在 docker-compose.yml 中配置重启策略&#xff08;推荐&#xff09;方法 2&#xff1a;创建 Systemd 服务&#xff08;更可靠&#xff09;方法 3&#xff1a;使用 Docker 的 Rest…

OpenZeppelin Contracts 架构分层分析

OpenZeppelin Contracts 是一个面向以太坊&#xff08;及兼容 EVM 的区块链&#xff09;生态系统的​​模块化、安全性优先、标准兼容的智能合约库​​。其内部代码按照功能职责与抽象层级&#xff0c;可系统性地划分为多个逻辑层次。理解这些层次及其依赖关系&#xff0c;对于…