刚接触MySQL数据库时,建表是最基础也是最重要的操作之一。就像盖房子需要先打地基一样,合理的表结构设计直接决定了后续数据操作的效率和便捷性。我在实际项目中发现,很多性能问题其实都源于最初建表时考虑不周。
MySQL建表主要涉及三个核心要素:表名定义、字段设计和约束条件。我们先从最基础的语法开始:
sql复制CREATE TABLE 表名 (
字段名1 数据类型 [约束条件],
字段名2 数据类型 [约束条件],
...
[表级约束条件]
);
这个简单的语法背后其实有很多需要注意的细节。比如表名和字段名的命名规范,不同数据类型的适用场景,以及各种约束条件的使用技巧。
MySQL提供了丰富的数据类型,选择合适的数据类型不仅能节省存储空间,还能提高查询效率。以下是几个最常用的数据类型:
提示:对于自增主键,如果没有特别大的数据量,使用INT就足够了,不必过度使用BIGINT。
字符串类型:
时间类型:
在实际项目中,字段设计有几个容易踩坑的地方:
VARCHAR长度设置:不要随意设置很大的长度,应根据实际需求合理设置。过大的长度会浪费内存。
小数精度:
NULL值处理:尽量设置NOT NULL约束,因为NULL值会导致索引失效等问题。
主键是表的唯一标识,设计时要注意:
sql复制-- 单字段主键
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(50)
);
-- 多字段联合主键
CREATE TABLE order_items (
order_id INT,
item_id INT,
PRIMARY KEY (order_id, item_id)
);
外键用于维护表间关系:
sql复制CREATE TABLE orders (
order_id INT PRIMARY KEY,
user_id INT,
FOREIGN KEY (user_id) REFERENCES users(id)
);
让我们通过一个电商系统的用户表来演示完整的建表过程:
sql复制CREATE TABLE `users` (
`user_id` INT NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`username` VARCHAR(50) NOT NULL COMMENT '用户名',
`password` CHAR(60) NOT NULL COMMENT '密码(加密存储)',
`email` VARCHAR(100) NOT NULL COMMENT '电子邮箱',
`phone` VARCHAR(20) COMMENT '手机号',
`birth_date` DATE COMMENT '出生日期',
`register_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '注册时间',
`last_login` TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '最后登录时间',
`status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态(1-正常,0-禁用)',
PRIMARY KEY (`user_id`),
UNIQUE KEY `idx_username` (`username`),
UNIQUE KEY `idx_email` (`email`),
KEY `idx_phone` (`phone`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户信息表';
这个例子包含了几个重要细节:
乱码是最常见的问题之一。建议统一使用utf8mb4字符集:
sql复制CREATE TABLE ... CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
MySQL主要存储引擎对比:
| 引擎 | 事务支持 | 锁粒度 | 适用场景 |
|---|---|---|---|
| InnoDB | 支持 | 行锁 | 大多数OLTP场景 |
| MyISAM | 不支持 | 表锁 | 读多写少场景 |
| MEMORY | 不支持 | 表锁 | 临时数据 |
注意:除非有特殊需求,否则建议使用InnoDB引擎。
根据我的项目经验,好的表设计应该遵循以下原则:
一个设计良好的用户表示例:
sql复制CREATE TABLE `users` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`user_no` VARCHAR(32) NOT NULL COMMENT '用户编号',
`username` VARCHAR(64) NOT NULL COMMENT '用户名',
`password` VARCHAR(128) NOT NULL COMMENT '密码',
`salt` VARCHAR(32) NOT NULL COMMENT '加密盐值',
`email` VARCHAR(128) COMMENT '邮箱',
`mobile` VARCHAR(20) COMMENT '手机号',
`avatar` VARCHAR(255) COMMENT '头像URL',
`gender` TINYINT DEFAULT 0 COMMENT '性别(0-未知,1-男,2-女)',
`birthday` DATE COMMENT '生日',
`status` TINYINT DEFAULT 1 COMMENT '状态(0-禁用,1-正常)',
`creator` VARCHAR(64) COMMENT '创建人',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` VARCHAR(64) COMMENT '更新人',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`is_deleted` TINYINT DEFAULT 0 COMMENT '删除标记(0-未删,1-已删)',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_user_no` (`user_no`),
UNIQUE KEY `uk_username` (`username`),
KEY `idx_mobile` (`mobile`),
KEY `idx_email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表';
建表后经常需要修改表结构,常用操作包括:
sql复制ALTER TABLE users ADD COLUMN nickname VARCHAR(50) COMMENT '昵称';
sql复制ALTER TABLE users MODIFY COLUMN email VARCHAR(150) COMMENT '电子邮箱';
sql复制ALTER TABLE users ADD INDEX idx_birthday (birth_date);
sql复制ALTER TABLE users COMMENT='用户基本信息表';
重要提示:生产环境修改大表结构时,建议在低峰期进行,并使用pt-online-schema-change等工具避免锁表。