MySQL 建库命令详解:从 CREATE DATABASE 到create table

一、了解数据类型

建表时最关键的决策之一就是字段类型的选择。MySQL 的数据类型大致分为数值、字符串、日期时间、二进制和 JSON 五大类,选型时优先考虑「够用就好」,避免盲目使用大类型。

1.1 数值类型

类型 字节 范围 / 说明 典型用途
TINYINT 1 -128 ~ 127(无符号 0 ~ 255) 状态、布尔标记
SMALLINT 2 -32768 ~ 32767 小范围计数
MEDIUMINT 3 -8388608 ~ 8388607 中等计数
INT 4 -2147483648 ~ 2147483647 主键、普通整数
BIGINT 8 -2^63 ~ 2^63-1 雪花 ID、超大计数
DECIMAL(M,D) 变长 精确小数,M 为总位数,D 为小数位 金额、精确计算
FLOAT / DOUBLE 4 / 8 近似浮点数,存在精度误差 科学计算、统计值

金额类字段务必使用 DECIMAL,不要用 FLOAT 或 DOUBLE,否则会出现精度丢失。整数类型可以加 UNSIGNED 表示非负,从而扩大正数范围。

sql 复制代码
CREATE TABLE t_account (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    balance DECIMAL(12,2) NOT NULL DEFAULT 0.00,
    status TINYINT UNSIGNED NOT NULL DEFAULT 0,
    PRIMARY KEY (id)
);

1.2 字符串类型

类型 说明 典型用途
CHAR(N) 定长字符串,不足补空格,N 最大 255 固定长度编码、性别等
VARCHAR(N) 变长字符串,需额外 1~2 字节记录长度 用户名、标题、地址
TINYTEXT / TEXT / MEDIUMTEXT / LONGTEXT 大文本,最大约 255B / 64KB / 16MB / 4GB 文章正文、日志、富文本
ENUM 枚举,只能取预设值之一 固定状态集合
SET 集合,可存多个预设值 多选标签

选型建议:长度基本固定的用 CHAR,长度变化大的用 VARCHAR;VARCHAR 的长度要按实际业务上限设置,不要一律写 255 或 1000。大文本字段尽量拆到独立表,避免影响主表查询性能。

sql 复制代码
CREATE TABLE t_user (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    username VARCHAR(32) NOT NULL,
    gender CHAR(1) NOT NULL DEFAULT 'U',
    intro TEXT,
    PRIMARY KEY (id),
    UNIQUE KEY uk_username (username)
);

1.3 日期时间类型

类型 字节 说明
DATE 3 日期,格式 YYYY-MM-DD
TIME 3 时间,格式 HH:MM:SS
DATETIME 8 日期时间,与时区无关,范围 1000 ~ 9999 年
TIMESTAMP 4 时间戳,随服务器时区转换,范围 1970 ~ 2038 年
YEAR 1 年份

业务时间字段推荐使用 DATETIME,不受时区和 2038 年问题影响;需要自动记录创建和更新时间时,可以配合 DEFAULT CURRENT_TIMESTAMP 和 ON UPDATE CURRENT_TIMESTAMP。

sql 复制代码
CREATE TABLE t_order (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
);

1.4 二进制与 JSON 类型

BINARY(N) 和 VARBINARY(N) 用于存储定长和变长二进制数据,BLOB 系列用于存储大块二进制内容(如图片、文件),但生产环境更推荐把文件放到对象存储,数据库只保存路径。

MySQL 5.7 起支持 JSON 类型,可以存储并校验 JSON 文档,配合 -> 和 ->> 操作符查询字段:

sql 复制代码
CREATE TABLE t_config (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    ext JSON,
    PRIMARY KEY (id)
);

INSERT INTO t_config (ext) VALUES ('{"theme":"dark","lang":"zh"}');

SELECT ext->>'$.theme' AS theme FROM t_config;

JSON 适合结构不固定的扩展字段,但高频查询和统计的字段仍应拆成独立列并建立索引。

1.5 选型小结

  • 能用小类型就不用大类型 :状态用 TINYINT,不要用 INT。
  • 金额用 DECIMAL,避免浮点误差。
  • 字符串按实际长度设置 ,VARCHAR 不要盲目给到最大值。
  • 时间优先 DATETIME,避免时区与 2038 年问题。
  • 大字段和 JSON 谨慎使用,高频查询字段应独立成列。

二、最基础的建库命令

MySQL 中创建数据库使用 CREATE DATABASE 语句,最简形式如下:

sql 复制代码
CREATE DATABASE mydb;

执行后会在当前实例中创建一个名为 mydb 的数据库。如果同名数据库已存在,MySQL 会报错 ERROR 1007 (HY000): Can't create database 'mydb'; database exists。

2.1 避免重复建库报错:IF NOT EXISTS

在脚本或自动化部署中,通常加上 IF NOT EXISTS,让命令具备幂等性:

sql 复制代码
CREATE DATABASE IF NOT EXISTS mydb;

这样当数据库已存在时,MySQL 只会给出一个 Warning,而不会中断执行。

三、查看库

建库之后,第一步通常是确认当前实例中有哪些数据库、当前连接的是哪个库,以及库的字符集和排序规则。以下命令无需切换数据库即可执行。

sql 复制代码
-- 查看当前实例中的所有数据库
SHOW DATABASES;

-- 查看库名匹配某个模式(支持 % 和 _ 通配符)
SHOW DATABASES LIKE 'my%';

-- 查看当前正在使用的数据库(未选择时返回 NULL)
SELECT DATABASE();

-- 查看指定库的创建语句(含字符集、排序规则)
SHOW CREATE DATABASE mydb;

其中 SHOW DATABASES 只列出当前账号有权限访问的库,看不到无权限的库属于正常现象;SHOW CREATE DATABASE 输出的信息最完整,排查字符集和排序规则问题时优先使用它。

常用命令速查:

  • SHOW DATABASES;:列出所有可见数据库。
  • SELECT DATABASE();:确认当前所在库。
  • SHOW CREATE DATABASE mydb;:查看库的字符集与排序规则。
  • information_schema.SCHEMATA:批量查询库元信息。
  • information_schema.TABLES:按库统计容量占用。

四、创建表

建库并切换到目标库后,就可以使用 CREATE TABLE 创建表。最简形式只需指定表名和字段定义:

sql 复制代码
USE mydb;

CREATE TABLE t_user (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    username VARCHAR(32) NOT NULL,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
);

其中 AUTO_INCREMENT 表示自增主键,NOT NULL 表示字段不可为空,DEFAULT 用于指定默认值。字段类型的选择可以参考前面的数据类型章节。

实际建表时通常还需要指定存储引擎、字符集和排序规则,并补充索引与注释:

sql 复制代码
CREATE TABLE t_order (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
    user_id BIGINT UNSIGNED NOT NULL COMMENT '用户 ID',
    order_no VARCHAR(32) NOT NULL COMMENT '订单号',
    amount DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '订单金额',
    status TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '状态:0 待支付,1 已支付',
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    PRIMARY KEY (id),
    UNIQUE KEY uk_order_no (order_no),
    KEY idx_user_id (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='订单表';
  • ENGINE=InnoDB:支持事务和行级锁,是生产环境的默认选择。
  • CHARSET=utf8mb4:完整支持中文和 Emoji,避免乱码问题。
  • UNIQUE KEY:唯一索引,用于保证业务唯一性,如订单号。
  • KEY:普通索引,用于加速按用户 ID 等字段的查询。
  • COMMENT:字段和表的注释,便于后续维护。

查看表

查看当前库中的所有表,可以使用 SHOW TABLES 语句,支持指定库名和模糊匹配:

sql 复制代码
-- 查看当前库中的所有表
SHOW TABLES;

-- 查看指定库中的表
SHOW TABLES FROM mydb;

-- 按模式匹配表名(支持 % 和 _ 通配符)
SHOW TABLES LIKE 't_%';

如果需要查看表的结构,可以使用 DESC 表名 或 SHOW CREATE TABLE 表名,后者输出的信息更完整,包含索引、引擎和字符集。

删除表

删除表使用 DROP TABLE 语句,语法如下:

sql 复制代码
DROP TABLE [IF EXISTS] 表名;

加上 IF EXISTS 可以避免表不存在时报错,让脚本具备幂等性。注意:DROP TABLE 会同时删除表结构和全部数据,且无法回滚,执行前务必确认。

修改表

表结构变更统一使用 ALTER TABLE 语句,下面按常见场景逐一说明。

1. 修改表名

方式一,使用 ALTER TABLE ... RENAME:

sql 复制代码
ALTER TABLE 表名 RENAME 新表名;

方式二,使用 RENAME TABLE ... TO,该方式还支持一次重命名多张表:

sql 复制代码
RENAME TABLE 表名 TO 新表名;
2. 新增列

语法如下,[AFTER 列名 | FIRST] 用于指定新列的位置,省略时默认追加到最后一列:

sql 复制代码
ALTER TABLE 表名 ADD 新列名 列类型 [AFTER 列名 | FIRST];

示例一,在表末尾增加一列 password:

sql 复制代码
ALTER TABLE student1 ADD password CHAR(8);

示例二,使用 AFTER 在指定列之后插入新列 notes:

sql 复制代码
ALTER TABLE student1 ADD notes VARCHAR(30) AFTER age;

示例三,使用 FIRST 在第一列插入新列:

sql 复制代码
ALTER TABLE student1 ADD aa INT FIRST;

注意:MySQL 没有 BEFORE 关键字,只能通过 AFTER 或 FIRST 控制位置。

3. 删除列

语法如下:

sql 复制代码
ALTER TABLE 表名 DROP 列名;

示例,删除上例中新增的 notes 和 aa 列:

sql 复制代码
ALTER TABLE student1 DROP notes;
ALTER TABLE student1 DROP aa;
4. 修改列名

使用 CHANGE 可以同时修改列名和列类型,旧列名和新列名都必须写全:

sql 复制代码
ALTER TABLE 表名 CHANGE 旧列名 新列名 列类型;

示例,把 password 改名为 passwd:

sql 复制代码
ALTER TABLE student1 CHANGE password passwd CHAR(8);
5. 修改列类型

只修改列类型、不改列名时使用 MODIFY:

sql 复制代码
ALTER TABLE 表名 MODIFY 列名 列类型;

示例,先新增一列 birthday,再把它修改为 DATE 类型:

sql 复制代码
ALTER TABLE student1 ADD birthday CHAR(10);
ALTER TABLE student1 MODIFY birthday DATE;
6. 修改列位置

使用 MODIFY 配合 AFTER 或 FIRST 可以调整列的位置:

sql 复制代码
ALTER TABLE 表名 MODIFY 列名 列类型 AFTER 某列;
ALTER TABLE 表名 MODIFY 列名 列类型 FIRST;

示例,把 notes 移动到 birthday 之后:

sql 复制代码
ALTER TABLE student1 MODIFY notes VARCHAR(30) AFTER birthday;

复制表

复制表结构

使用 LIKE 只复制表结构,不复制数据:

sql 复制代码
CREATE TABLE 新表名 LIKE 源表;
复制表结构 + 数据

使用 CREATE TABLE ... SELECT 可以同时复制结构和数据:

sql 复制代码
CREATE TABLE 新表名 SELECT * FROM 源表;

注意:这种方式不会复制源表的索引、主键和自增属性,需要的话要手动补充。

复制表数据

如果目标表已经存在,只想复制数据,使用 INSERT INTO ... SELECT:

sql 复制代码
INSERT INTO 新表名 SELECT * FROM 源表;

如果两张表的列不完全一致,建议显式写出列名,避免因列顺序不同导致数据错位:

sql 复制代码
INSERT INTO 新表名 (id, username, created_at)
SELECT id, username, created_at FROM 源表;

总结

下面用一张速查表汇总本文涉及的核心 SQL 语句,方便日常查阅。

操作分类 核心 SQL 语句 用途说明
建库 CREATE DATABASE [IF NOT EXISTS] 库名; 创建数据库,加 IF NOT EXISTS 可保证幂等
查看库 SHOW DATABASES; / SELECT DATABASE(); / SHOW CREATE DATABASE 库名; 列出所有库、确认当前库、查看库的字符集与排序规则
建表 CREATE TABLE 表名 (字段定义, 索引) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 创建表结构,指定字段类型、主键、索引、引擎和字符集
查看表 SHOW TABLES; / DESC 表名; / SHOW CREATE TABLE 表名; 列出表、查看字段结构、查看完整建表语句
删除表 DROP TABLE [IF EXISTS] 表名; 删除表结构和全部数据,不可回滚,需谨慎执行
修改表名 ALTER TABLE 表名 RENAME 新表名; / RENAME TABLE 表名 TO 新表名; 重命名表,后者支持一次重命名多张表
新增列 `ALTER TABLE 表名 ADD 列名 列类型 [AFTER 列名 FIRST];`
删除列 ALTER TABLE 表名 DROP 列名; 删除字段及其数据
修改列名 ALTER TABLE 表名 CHANGE 旧列名 新列名 列类型; 同时修改列名和列类型
修改列类型 ALTER TABLE 表名 MODIFY 列名 列类型; 只改类型,不改列名
修改列位置 `ALTER TABLE 表名 MODIFY 列名 列类型 [AFTER 某列 FIRST];`
复制表结构 CREATE TABLE 新表名 LIKE 源表; 只复制结构,含索引,不含数据
复制表结构 + 数据 CREATE TABLE 新表名 SELECT * FROM 源表; 同时复制结构和数据,但不复制索引与自增属性
复制表数据 INSERT INTO 新表名 SELECT * FROM 源表; 目标表已存在时只复制数据,建议显式写出列名

建表与改表的三条最佳实践:

  1. 字段类型够用就好 :状态用 TINYINT、金额用 DECIMAL、时间优先 DATETIME,VARCHAR 按实际业务上限设置,避免盲目使用大类型造成空间浪费和性能下降。
  2. 建表时一次把约束和索引写全 :主键、NOT NULL、默认值、唯一索引、普通索引、ENGINE=InnoDB、CHARSET=utf8mb4 和 COMMENT 尽量在建表阶段确定,减少后期反复 ALTER TABLE。
  3. 改表前先评估影响并做好备份 :大表执行 ALTER TABLE 可能长时间锁表,建议在低峰期操作、先在测试库验证,并确认 DROP 类操作已加 IF EXISTS 且数据可恢复。
相关推荐
SelectDB1 小时前
Doris 异步物化视图实战:与 Snowflake MV / Dynamic Tables 分层建模对照
大数据·数据库·云原生
张张123y2 小时前
后端第十六课:Multi-Agent 多智能体(让多个 Agent 分工协作)
大数据·数据库·人工智能·python·deepseek·dsh·agent 框架
todoitbo2 小时前
MongoDB迁移之后,Spring Data 和 Hibernate 各自接哪类请求
大数据·数据库·mongodb·spring·hibernate·金仓数据库
HEJOO93 小时前
数据库日期类型字段如何选型:跨数据库兼容的实践指南
数据库
这个DBA有点耶3 小时前
主库秒级,从库延迟2小时:深挖Online DDL回放的MDL阻塞与算法降级机制
数据库·sql·dba
xcLeigh3 小时前
KingbaseES数据库教程:初识数据库,从安装到跑通第一条SQL
android·数据库·sql·安装·数据库教程·kes
知行产研3 小时前
解读〈工程机械行业“十五五“发展规划〉:从卖整机到卖解决方案
数据库·mysql
handsome_sai3 小时前
SQL Server 快速入门
数据库·sqlserver
底层玩家老张3 小时前
RAG向量库拆分复盘:内存、延迟与权限的三笔账
数据库·向量数据库·向量检索·ai数据库