【零基础学MySQL】第四章:DDL详解

在 MySQL 数据库的日常操作中,DDL(Data Definition Language,数据定义语言)扮演着至关重要的角色。它负责定义和管理数据库对象,如数据库、表、列、索引等,是数据库设计和维护的基础。对于开发者和数据库管理员而言,熟练掌握 DDL 不仅能规范数据库结构,还能提升数据存储效率和系统稳定性。本文将从 DDL 的基本概念入手,结合丰富的示例,详细讲解 MySQL 中常用的 DDL 语句,帮助读者全面理解并灵活运用。

一、DDL 概述:定义数据库的 "骨架"

1.1 什么是 DDL?

DDL 是 SQL 语言的三大核心部分之一(另外两部分是 DML 数据操纵语言和 DCL 数据控制语言),主要用于创建、修改和删除数据库对象。它的操作会直接影响数据库的结构,而不涉及具体的数据内容。例如,创建一个存储用户信息的表、为表添加新的字段、删除无用的索引等,都需要通过 DDL 语句来实现。

1.2 DDL 的核心特点

  • 操作对象是数据库结构:DDL 针对的是数据库、表、列、索引等 "框架性" 对象,而非表中的具体数据行。

  • 执行后立即生效且不可回滚:与 DML 不同,DDL 语句执行后会直接修改数据库结构,且 MySQL 默认不支持 DDL 的回滚(即使开启事务也无法回滚 DDL 操作),因此执行前需格外谨慎。

  • 会加锁影响性能:执行 DDL 语句时,MySQL 可能会对相关表加锁(如排他锁),导致其他操作(如查询、更新)阻塞,尤其是在高并发场景下,需合理安排 DDL 执行时间。

二、数据库级 DDL:创建与管理数据库

数据库是存储表和其他对象的容器,首先需要通过 DDL 语句创建和管理数据库。常用的数据库级 DDL 语句包括CREATE DATABASEALTER DATABASEDROP DATABASE

2.1 创建数据库(CREATE DATABASE)

创建数据库是最基础的 DDL 操作,语法如下:

复制代码
CREATE DATABASE [IF NOT EXISTS] 数据库名

[DEFAULT CHARACTER SET 字符集]

[DEFAULT COLLATE 排序规则];
  • IF NOT EXISTS:可选参数,用于避免因数据库已存在而报错。

  • DEFAULT CHARACTER SET:指定数据库的默认字符集(如 utf8mb4,支持 emoji 表情)。

  • DEFAULT COLLATE:指定数据库的默认排序规则(如 utf8mb4_general_ci,不区分大小写)。

示例 1:创建基础数据库
sql 复制代码
-- 创建名为test_db的数据库,若已存在则不执行

CREATE DATABASE IF NOT EXISTS test_db;
示例 2:创建指定字符集和排序规则的数据库
sql 复制代码
-- 创建支持emoji且不区分大小写的数据库

CREATE DATABASE IF NOT EXISTS user_db

DEFAULT CHARACTER SET utf8mb4

DEFAULT COLLATE utf8mb4_general_ci;

2.2 修改数据库属性(ALTER DATABASE)

ALTER DATABASE用于修改数据库的默认字符集、排序规则等属性,语法如下:

复制代码
ALTER DATABASE 数据库名

[DEFAULT CHARACTER SET 新字符集]

[DEFAULT COLLATE 新排序规则];
示例:修改数据库的字符集
sql 复制代码
-- 将test_db的默认字符集改为utf8mb4

ALTER DATABASE test_db

DEFAULT CHARACTER SET utf8mb4

DEFAULT COLLATE utf8mb4_general_ci;

2.3 删除数据库(DROP DATABASE)

DROP DATABASE用于删除整个数据库(包括数据库中的所有表和数据),语法如下:

复制代码
DROP DATABASE [IF EXISTS] 数据库名;
  • IF EXISTS:可选参数,避免因数据库不存在而报错。
示例:删除数据库
sql 复制代码
-- 若test_db存在,则删除该数据库(谨慎执行!)

DROP DATABASE IF EXISTS test_db;

⚠️ 注意:

DROP DATABASE

是高危操作,执行后数据库及其所有内容将被永久删除,无法恢复。在生产环境中,需提前备份数据,并严格控制权限。

三、表级 DDL:创建与管理数据表

表是数据库中存储数据的核心对象,表级 DDL 是 DDL 中最常用的部分,包括CREATE TABLE(创建表)、ALTER TABLE(修改表)、DROP TABLE(删除表)等。

3.1 创建表(CREATE TABLE)

CREATE TABLE用于定义表的结构,包括表名、列名、数据类型、约束条件等,语法如下:

复制代码
CREATE TABLE [IF NOT EXISTS] 表名 (

     列名1 数据类型 [约束条件],

     列名2 数据类型 [约束条件],

     ...

     [表级约束条件]

) [ENGINE=存储引擎] [DEFAULT CHARSET=字符集];
  • IF NOT EXISTS:避免表已存在时报错。

  • 数据类型:指定列存储数据的类型(如 INT、VARCHAR、DATETIME 等)。

  • 约束条件:保证数据完整性的规则(如主键、非空、唯一、外键等)。

  • ENGINE:指定表的存储引擎(如 InnoDB,支持事务和外键;MyISAM,查询性能优但不支持事务)。

示例:创建用户表(user_info)
sql 复制代码
-- 在user_db数据库中创建用户表

USE user_db;

CREATE TABLE IF NOT EXISTS user_info (

    id INT UNSIGNED NOT NULL AUTO_INCREMENT,  -- 用户ID,无符号整数,自增

    username VARCHAR(50) NOT NULL COMMENT '用户名',  -- 用户名,非空

    phone CHAR(11) NOT NULL UNIQUE COMMENT '手机号,唯一',  -- 手机号,唯一且非空

    email VARCHAR(100) UNIQUE COMMENT '邮箱,唯一(可空)',  -- 邮箱,唯一

    gender TINYINT DEFAULT 0 COMMENT '性别:0-未知,1-男,2-女',  -- 性别,默认0

    create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',  -- 创建时间,默认当前时间

    update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间,更新时自动刷新',  -- 更新时间

    PRIMARY KEY (id)  -- 主键约束,主键为id

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户信息表';

上述示例中包含了多个关键知识点:

  • 数据类型INT UNSIGNED(无符号整数)、VARCHAR(50)(可变长度字符串,最大 50 字符)、CHAR(11)(固定长度字符串,适合手机号)、TINYINT( tiny 整数)、DATETIME(日期时间类型)。

  • 约束条件

    • NOT NULL:列值不能为空(如 username、phone)。

    • UNIQUE:列值唯一(如 phone、email,避免重复)。

    • AUTO_INCREMENT:列值自动递增(仅用于整数主键,如 id)。

    • DEFAULT:指定列的默认值(如 gender 默认 0,create_time 默认当前时间)。

    • PRIMARY KEY:主键约束,唯一标识表中的每一行(如 id 作为主键)。

  • COMMENT:为表和列添加注释,提高代码可读性(如 "用户信息表""用户名")。

  • 存储引擎:使用 InnoDB 存储引擎,支持事务和外键,适合业务表。

3.2 修改表结构(ALTER TABLE)

ALTER TABLE是表级 DDL 中最灵活的语句,可用于添加列、修改列、删除列、修改约束等,语法根据操作类型不同而变化,核心格式如下:

复制代码
ALTER TABLE 表名

操作类型 [具体参数];

常用的操作类型包括ADD(添加列)、MODIFY(修改列)、CHANGE(修改列名和属性)、DROP(删除列)、ADD CONSTRAINT(添加约束)等。

示例 1:添加新列
sql 复制代码
-- 为user_info表添加"年龄"列(age),允许为空,默认值为0

ALTER TABLE user_info

ADD COLUMN age TINYINT UNSIGNED DEFAULT 0 COMMENT '年龄' AFTER username;

-- AFTER username:指定列添加在username之后(可选,默认添加在最后)
示例 2:修改列的属性
sql 复制代码
-- 将age列的默认值改为18,且设置为非空

ALTER TABLE user_info

MODIFY COLUMN age TINYINT UNSIGNED NOT NULL DEFAULT 18 COMMENT '年龄';

-- MODIFY仅修改列的属性(数据类型、约束等),不修改列名
示例 3:修改列名和属性
sql 复制代码
-- 将"age"列改名为"user_age",同时将数据类型改为SMALLINT

ALTER TABLE user_info

CHANGE COLUMN age user_age SMALLINT UNSIGNED NOT NULL DEFAULT 18 COMMENT '用户年龄';

-- CHANGE需同时指定旧列名和新列名,可修改列名+属性
示例 4:删除列
sql 复制代码
-- 删除user_info表中的"email"列(谨慎执行!删除后列数据丢失)

ALTER TABLE user_info

DROP COLUMN email;
示例 5:添加唯一约束
sql 复制代码
-- 为"phone"列添加唯一约束(若之前未添加)

ALTER TABLE user_info

ADD UNIQUE INDEX idx_unique_phone (phone) COMMENT '手机号唯一索引';

-- 这里通过索引实现唯一约束,同时提升查询效率
示例 6:修改表名
sql 复制代码
-- 将user_info表改名为user_details

ALTER TABLE user_info

RENAME TO user_details;

3.3 删除表(DROP TABLE)

DROP TABLE用于删除数据表(包括表结构和所有数据),语法如下:

复制代码
DROP TABLE [IF EXISTS] 表名1, 表名2, ...;
  • 支持同时删除多个表,用逗号分隔表名。
示例:删除表
sql 复制代码
-- 若user_details表存在,则删除该表(谨慎执行!)

DROP TABLE IF EXISTS user_details;

-- 同时删除多个表

DROP TABLE IF EXISTS table1, table2;

⚠️ 注意:

DROP TABLE

会永久删除表结构和数据,无法恢复,执行前需确认必要性并备份数据。

3.4 清空表数据(TRUNCATE TABLE)

虽然TRUNCATE TABLE不直接修改表结构,但它属于 DDL 语句(因为会重置表的自增计数器、释放存储空间),用于清空表中的所有数据,语法如下:

复制代码
TRUNCATE TABLE [IF EXISTS] 表名;
示例:清空表数据
sql 复制代码
-- 清空user_details表中的所有数据(保留表结构)

TRUNCATE TABLE IF EXISTS user_details;

TRUNCATE DELETE的区别

  • TRUNCATE是 DDL,不可回滚,清空数据后自增计数器重置(如 id 从 1 重新开始),执行速度快。

  • DELETE是 DML,可回滚(需在事务中),自增计数器不重置,执行速度慢(需逐行删除)。

四、索引级 DDL:创建与管理索引

索引是提升 MySQL 查询性能的关键,通过 DDL 语句可以创建、修改和删除索引。常用的索引类型包括主键索引、唯一索引、普通索引、联合索引等。

4.1 创建索引(CREATE INDEX)

CREATE INDEX用于为表添加索引,语法如下:

sql 复制代码
-- 普通索引

CREATE [INDEX | KEY] 索引名

ON 表名 (列名1 [ASC|DESC], 列名2 [ASC|DESC], ...)

[COMMENT '索引注释'];

-- 唯一索引

CREATE UNIQUE [INDEX | KEY] 索引名

ON 表名 (列名1, 列名2, ...)

[COMMENT '索引注释'];
  • 普通索引:无唯一性约束,仅用于提升查询速度。

  • 唯一索引:列值唯一(允许空值,但空值仅出现一次),兼具唯一性约束和查询优化作用。

示例 1:创建普通索引
sql 复制代码
-- 为user_details表的"username"列创建普通索引,提升用户名查询速度

CREATE INDEX idx_user_username 

ON user_details (username) 

COMMENT '用户名普通索引';
示例 2:创建唯一索引
sql 复制代码
-- 为"phone"列创建唯一索引,确保手机号唯一且提升查询速度

CREATE UNIQUE INDEX idx_unique_user_phone 

ON user_details (phone) 

COMMENT '手机号唯一索引';
示例 3:创建联合索引

联合索引(多列索引)适用于查询条件包含多个列的场景,遵循 "最左前缀原则"(查询时需从索引的第一列开始匹配)。

sql 复制代码
-- 为"username"和"user_age"创建联合索引,优化多条件查询

CREATE INDEX idx_user_name_age 

ON user_details (username, user_age) 

COMMENT '用户名+年龄联合索引';

4.2 删除索引(DROP INDEX)

DROP INDEX用于删除表中的索引,语法如下:

复制代码
DROP INDEX 索引名 ON 表名;
示例:删除索引
sql 复制代码
-- 删除user_details表中的"idx_user_username"索引

DROP INDEX idx_user_username ON user_details;

4.3 查看表中的索引

虽然SHOW INDEX不是 DDL 语句,但它是查看索引信息的常用命令,可辅助 DDL 操作:

sql 复制代码
-- 查看user_details表的所有索引

SHOW INDEX FROM user_details;

五、DDL 操作的注意事项与最佳实践

5.1 执行 DDL 前的准备

  • 备份数据 :DDL 操作(如DROP DATABASEDROP TABLETRUNCATE)会导致数据丢失,执行前必须备份核心数据。

  • 检查依赖关系:删除表或修改列时,需检查是否有外键依赖(如 A 表的外键关联 B 表的主键,删除 B 表前需先删除 A 表的外键约束)。

  • 选择低峰期执行:DDL 可能加锁阻塞业务,建议在业务低峰期(如凌晨)执行,减少对用户的影响。

5.2 避免高频 DDL 操作

频繁修改表结构(如频繁添加 / 删除列、索引)会导致:

  • 数据库锁竞争加剧,影响并发性能。

  • 索引碎片化,降低查询效率(需定期优化索引)。

5.3 合理使用约束和索引

  • 约束:根据业务需求添加约束(如主键、唯一键),避免冗余约束(如已加主键,无需再对主键列加唯一约束)。

  • 索引:索引并非越多越好,过多索引会降低插入 / 更新 / 删除的性能(需维护索引)。建议只为高频查询的列创建索引,且避免重复索引(如联合索引已包含单列索引的功能)。

5.4 兼容不同 MySQL 版本

部分 DDL 语法在不同 MySQL 版本中存在差异,例如:

  • MySQL 8.0 支持ALTER TABLE ... RENAME COLUMN,而 5.7 需用CHANGE COLUMN

  • MySQL 8.0 默认字符集为 utf8mb4,5.7 默认是 latin1,创建数据库时需显式指定字符集。

    在跨版本环境中,需注意语法兼容性。

六、总结

DDL 是 MySQL 数据库设计和维护的核心工具,涵盖了数据库、表、索引等对象的创建、修改和删除操作。本文通过详细的语法讲解和示例,从基础到实践全面梳理了 DDL 的关键知识点,包括:

  • 数据库级 DDL:CREATE DATABASEALTER DATABASEDROP DATABASE

  • 表级 DDL:CREATE TABLEALTER TABLEDROP TABLETRUNCATE TABLE

  • 索引级 DDL:CREATE INDEXDROP INDEX

  • DDL 操作的注意事项和最佳实践。

掌握 DDL 不仅能帮助开发者规范数据库结构,还能提升系统性能和稳定性。在实际应用中,需结合业务场景合理使用 DDL,同时注意数据安全和操作风险,避免因不当操作导致数据丢失或系统故障。

相关推荐
程序新视界7 小时前
MySQL的隔离级别及其工作原理详解
数据库·后端·mysql
少林码僧7 小时前
1.1 大语言模型调用方式与函数调用(Function Calling):从基础到实战
人工智能·ai·语言模型·自然语言处理·llm·1024程序员节
liliangcsdn8 小时前
如何基于llm+mysql构建轻量级全文搜索
数据库·人工智能·mysql
胖虎18 小时前
Swift项目生成Framework流程以及与OC的区别
framework·swift·1024程序员节·swift framework
李慕婉学姐8 小时前
Springboot微信小程序在线考试系统w47h61gy(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·微信小程序
啊吧怪不啊吧8 小时前
SQL之表的查改(下)
大数据·数据库·sql
工具人55559 小时前
adb disable-verity
数据库·数据仓库·adb
白露与泡影10 小时前
Redis:我是如何与客户端进行通信的
数据库·redis·缓存
一只小bit14 小时前
MySQL 索引:从聚簇到普通索引,如何加快查询效率?
数据库·mysql·oracle