数据定义语言(DDL)概述
数据定义语言(Data Definition Language,DDL)是SQL语言的一个重要组成部分,用于定义和管理数据库中的各种对象结构。DDL命令允许数据库管理员和开发人员创建、修改和删除数据库对象,如数据库、表、索引、视图等。
主要的DDL命令包括:
- CREATE - 创建数据库对象
- ALTER - 修改数据库对象结构
- DROP - 删除数据库对象
- TRUNCATE - 清空表数据
- RENAME - 重命名数据库对象
DDL的重要性
DDL在数据库管理中具有以下重要作用:
- 数据结构定义 - 定义数据的存储结构和关系
- 数据完整性 - 通过约束保证数据的准确性和一致性
- 性能优化 - 通过索引和分区提高查询性能
- 数据安全 - 通过视图和权限控制保护敏感数据
- 系统维护 - 支持数据库结构的变更和演化
数据库操作
数据库是MySQL中最高级别的组织单位,包含表、视图、存储过程等对象。
创建数据库
SQL语法
CREATE DATABASE [IF NOT EXISTS] database_name
[CHARACTER SET charset_name]
[COLLATE collation_name]
[ENCRYPTION [=] 'Y'];
SQL示例
-- 创建简单数据库
CREATE DATABASE my_shop;
-- 创建带字符集的数据库
CREATE DATABASE my_blog
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
-- 安全创建数据库(如果不存在)
CREATE DATABASE IF NOT EXISTS my_app;
-- 创建加密数据库(MySQL 8.0.16+)
CREATE DATABASE secure_db
CHARACTER SET utf8mb4
ENCRYPTION = 'Y';
查看数据库
SQL示例
-- 查看所有数据库
SHOW DATABASES;
-- 查看数据库创建语句
SHOW CREATE DATABASE my_shop;
-- 查看当前数据库
SELECT DATABASE();
-- 查看数据库字符集和排序规则
SELECT schema_name, default_character_set_name, default_collation_name
FROM information_schema.schemata
WHERE schema_name = 'my_shop';
选择数据库
SQL示例
USE my_shop;
修改数据库
SQL语法
ALTER DATABASE database_name
[CHARACTER SET charset_name]
[COLLATE collation_name]
[ENCRYPTION [=] 'Y'];
SQL示例
-- 修改数据库字符集
ALTER DATABASE my_shop
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
-- 启用数据库加密
ALTER DATABASE my_shop ENCRYPTION = 'Y';
删除数据库
SQL语法
DROP DATABASE [IF EXISTS] database_name;
SQL示例
-- 删除数据库
DROP DATABASE old_database;
-- 安全删除数据库(如果存在)
DROP DATABASE IF EXISTS temporary_db;
注意:DROP DATABASE命令会永久删除数据库及其所有数据,操作前请务必确认。建议在执行前先备份数据。
表操作
表是数据库中存储数据的基本单位,由行和列组成。正确的表设计对数据库性能和数据完整性至关重要。
创建表
SQL语法
CREATE TABLE [IF NOT EXISTS] table_name (
column1 datatype [constraints],
column2 datatype [constraints],
...
[table_constraints]
) [table_options];
表选项说明
- ENGINE - 存储引擎,如InnoDB、MyISAM
- CHARACTER SET - 字符集
- COLLATE - 排序规则
- ROW_FORMAT - 行格式,如COMPACT、DYNAMIC
- COMMENT - 表注释
SQL示例 - 创建用户表
CREATE TABLE IF NOT EXISTS users (
user_id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
first_name VARCHAR(50),
last_name VARCHAR(50),
birth_date DATE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
is_active BOOLEAN DEFAULT TRUE,
INDEX idx_username (username),
INDEX idx_email (email),
INDEX idx_fullname (last_name, first_name)
) ENGINE=InnoDB CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户信息表';
SQL示例 - 创建产品表
CREATE TABLE products (
product_id INT AUTO_INCREMENT PRIMARY KEY,
product_name VARCHAR(100) NOT NULL,
description TEXT,
price DECIMAL(10, 2) NOT NULL CHECK (price >= 0),
cost_price DECIMAL(10, 2) NOT NULL,
stock_quantity INT DEFAULT 0 CHECK (stock_quantity >= 0),
category_id INT,
supplier_id INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (category_id) REFERENCES categories(category_id),
FOREIGN KEY (supplier_id) REFERENCES suppliers(supplier_id),
INDEX idx_product_name (product_name),
INDEX idx_category (category_id),
INDEX idx_price (price),
UNIQUE INDEX idx_product_supplier (product_name, supplier_id)
) ENGINE=InnoDB;
SQL示例 - 创建订单表
CREATE TABLE orders (
order_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
total_amount DECIMAL(10, 2) NOT NULL,
status ENUM('pending', 'confirmed', 'shipped', 'delivered', 'cancelled') DEFAULT 'pending',
shipping_address TEXT,
billing_address TEXT,
notes TEXT,
FOREIGN KEY (user_id) REFERENCES users(user_id),
INDEX idx_user_id (user_id),
INDEX idx_order_date (order_date),
INDEX idx_status (status)
) ENGINE=InnoDB;
查看表结构
SQL示例
-- 查看所有表
SHOW TABLES;
-- 查看表结构
DESCRIBE users;
DESC users; -- 简写
-- 查看表创建语句
SHOW CREATE TABLE users;
-- 查看表详细信息
SELECT * FROM information_schema.tables
WHERE table_schema = 'my_shop' AND table_name = 'users';
-- 查看列信息
SELECT column_name, data_type, is_nullable, column_default, column_comment
FROM information_schema.columns
WHERE table_schema = 'my_shop' AND table_name = 'users'
ORDER BY ordinal_position;
修改表
ALTER TABLE命令用于修改表结构,是数据库维护中最常用的DDL命令之一。
添加列
SQL语法
ALTER TABLE table_name
ADD COLUMN column_name datatype [constraints]
[FIRST | AFTER existing_column];
SQL示例
-- 添加电话号码列
ALTER TABLE users
ADD COLUMN phone_number VARCHAR(20);
-- 添加带约束的列
ALTER TABLE users
ADD COLUMN last_login TIMESTAMP,
ADD COLUMN login_count INT DEFAULT 0;
-- 在特定位置添加列
ALTER TABLE users
ADD COLUMN middle_name VARCHAR(50) AFTER first_name;
-- 添加列到表首
ALTER TABLE users
ADD COLUMN internal_id INT FIRST;
修改列
SQL语法
ALTER TABLE table_name
MODIFY COLUMN column_name new_datatype [new_constraints]
[FIRST | AFTER existing_column];
SQL示例
-- 修改列数据类型
ALTER TABLE users
MODIFY COLUMN username VARCHAR(100) NOT NULL;
-- 修改默认值
ALTER TABLE products
MODIFY COLUMN stock_quantity INT DEFAULT 10;
-- 修改列位置
ALTER TABLE users
MODIFY COLUMN email VARCHAR(100) AFTER username;
-- 修改多个列
ALTER TABLE users
MODIFY COLUMN first_name VARCHAR(100),
MODIFY COLUMN last_name VARCHAR(100);
删除列
SQL语法
ALTER TABLE table_name
DROP COLUMN column_name;
SQL示例
ALTER TABLE users
DROP COLUMN phone_number;
-- 删除多个列
ALTER TABLE users
DROP COLUMN temp_col1,
DROP COLUMN temp_col2;
重命名列
SQL语法
ALTER TABLE table_name
CHANGE COLUMN old_column_name new_column_name datatype [constraints];
SQL示例
ALTER TABLE users
CHANGE COLUMN first_name given_name VARCHAR(50);
-- 重命名并修改数据类型
ALTER TABLE products
CHANGE COLUMN item_name product_name VARCHAR(200) NOT NULL;
添加约束
SQL示例
-- 添加主键约束
ALTER TABLE table_name
ADD PRIMARY KEY (column_name);
-- 添加外键约束
ALTER TABLE table_name
ADD FOREIGN KEY (column_name) REFERENCES parent_table(parent_column);
-- 添加唯一约束
ALTER TABLE table_name
ADD UNIQUE (column_name);
-- 添加检查约束(MySQL 8.0.16+)
ALTER TABLE products
ADD CONSTRAINT chk_price CHECK (price > cost_price);
删除约束
SQL示例
-- 删除主键约束
ALTER TABLE table_name
DROP PRIMARY KEY;
-- 删除外键约束
ALTER TABLE table_name
DROP FOREIGN KEY constraint_name;
-- 删除唯一约束
ALTER TABLE table_name
DROP INDEX constraint_name;
重命名表
SQL语法
RENAME TABLE old_table_name TO new_table_name;
SQL示例
RENAME TABLE users TO customers;
-- 重命名多个表
RENAME TABLE
old_table1 TO new_table1,
old_table2 TO new_table2;
删除表
SQL语法
DROP TABLE [IF EXISTS] table_name;
SQL示例
DROP TABLE temporary_data;
-- 安全删除表
DROP TABLE IF EXISTS old_table;
-- 删除多个表
DROP TABLE table1, table2, table3;
注意:DROP TABLE命令会永久删除表及其所有数据,操作前请务必确认。建议在执行前先备份数据。
清空表
SQL语法
TRUNCATE TABLE table_name;
SQL示例
TRUNCATE TABLE audit_logs;
TRUNCATE vs DELETE:
- TRUNCATE删除所有数据并重置自增计数器,比DELETE更快
- TRUNCATE不能使用WHERE条件,而DELETE可以
- TRUNCATE是DDL操作,而DELETE是DML操作
- TRUNCATE不能回滚,而DELETE可以(在事务中)
- TRUNCATE会释放表空间,而DELETE不会
索引操作
索引是提高查询性能的重要工具,但会增加插入、更新和删除操作的开销。
创建索引
SQL语法
-- 创建普通索引
CREATE INDEX index_name ON table_name (column_name);
-- 创建唯一索引
CREATE UNIQUE INDEX index_name ON table_name (column_name);
-- 创建复合索引
CREATE INDEX index_name ON table_name (col1, col2);
-- 创建全文索引
CREATE FULLTEXT INDEX index_name ON table_name (column_name);
-- 创建空间索引
CREATE SPATIAL INDEX index_name ON table_name (column_name);
SQL示例
-- 在用户名上创建索引
CREATE INDEX idx_username ON users (username);
-- 在姓和名上创建复合索引
CREATE INDEX idx_fullname ON users (last_name, first_name);
-- 在邮箱上创建唯一索引
CREATE UNIQUE INDEX idx_unique_email ON users (email);
-- 在产品描述上创建全文索引
CREATE FULLTEXT INDEX idx_product_desc ON products (description);
-- 创建前缀索引
CREATE INDEX idx_product_name_prefix ON products (product_name(20));
删除索引
SQL语法
DROP INDEX index_name ON table_name;
SQL示例
DROP INDEX idx_username ON users;
查看索引
SQL示例
-- 查看表的所有索引
SHOW INDEX FROM users;
-- 从信息模式查看索引
SELECT index_name, column_name, index_type, non_unique
FROM information_schema.statistics
WHERE table_schema = 'my_shop' AND table_name = 'users';
视图操作
视图是基于SQL查询结果的虚拟表,可以简化复杂查询、提高安全性和实现数据抽象。
创建视图
SQL语法
CREATE VIEW view_name [(column_list)] AS
select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION];
SQL示例
-- 创建活跃用户视图
CREATE VIEW active_users AS
SELECT user_id, username, email, first_name, last_name
FROM users
WHERE is_active = 1;
-- 创建产品销售统计视图
CREATE VIEW product_sales AS
SELECT
p.product_name,
c.category_name,
SUM(oi.quantity) AS total_sold,
SUM(oi.quantity * oi.unit_price) AS total_revenue
FROM products p
JOIN categories c ON p.category_id = c.category_id
JOIN order_items oi ON p.product_id = oi.product_id
GROUP BY p.product_id, p.product_name, c.category_name;
-- 创建可更新视图
CREATE VIEW user_profiles AS
SELECT user_id, username, first_name, last_name, email
FROM users
WHERE is_active = 1
WITH CHECK OPTION;
使用视图
SQL示例
-- 查询视图
SELECT * FROM active_users;
-- 对视图进行条件查询
SELECT * FROM product_sales
WHERE total_revenue > 1000
ORDER BY total_sold DESC;
-- 更新视图(如果视图是可更新的)
UPDATE user_profiles
SET first_name = 'John'
WHERE user_id = 1;
修改视图
SQL语法
ALTER VIEW view_name [(column_list)] AS
select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION];
SQL示例
ALTER VIEW active_users AS
SELECT user_id, username, email, first_name, last_name, created_at
FROM users
WHERE is_active = 1;
删除视图
SQL语法
DROP VIEW [IF EXISTS] view_name;
SQL示例
DROP VIEW active_users;
-- 安全删除视图
DROP VIEW IF EXISTS old_view;
表分区
表分区是将大表分割成更小、更易管理的部分,可以提高查询性能和数据管理效率。
创建分区表
SQL示例
-- 按范围分区
CREATE TABLE sales (
sale_id INT AUTO_INCREMENT,
sale_date DATE,
amount DECIMAL(10, 2),
PRIMARY KEY (sale_id, sale_date)
)
PARTITION BY RANGE (YEAR(sale_date)) (
PARTITION p0 VALUES LESS THAN (2020),
PARTITION p1 VALUES LESS THAN (2021),
PARTITION p2 VALUES LESS THAN (2022),
PARTITION p3 VALUES LESS THAN (2023),
PARTITION p_max VALUES LESS THAN MAXVALUE
);
-- 按列表分区
CREATE TABLE employees (
emp_id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100),
department VARCHAR(50)
)
PARTITION BY LIST COLUMNS (department) (
PARTITION p_sales VALUES IN ('Sales', 'Marketing'),
PARTITION p_tech VALUES IN ('IT', 'Engineering'),
PARTITION p_other VALUES IN ('HR', 'Finance', 'Operations')
);
管理分区
SQL示例
-- 添加分区
ALTER TABLE sales ADD PARTITION (
PARTITION p4 VALUES LESS THAN (2024)
);
-- 删除分区
ALTER TABLE sales DROP PARTITION p0;
-- 重组分区
ALTER TABLE sales REORGANIZE PARTITION p_max INTO (
PARTITION p4 VALUES LESS THAN (2024),
PARTITION p_max VALUES LESS THAN MAXVALUE
);
DDL最佳实践
设计原则
- 规范化设计 - 遵循数据库规范化原则,减少数据冗余
- 命名规范 - 使用有意义的表名和列名,保持一致性
- 数据类型选择 - 选择最适合数据特性的数据类型
- 约束使用 - 充分利用约束保证数据完整性
- 索引策略 - 为常用查询字段创建索引,但避免过度索引
性能考虑
- 为大型表考虑分区策略
- 选择合适的存储引擎(通常推荐InnoDB)
- 考虑字符集和排序规则对性能的影响
- 为频繁查询的列创建合适的索引
- 避免在高峰时段执行DDL操作
维护建议
- 定期分析表结构和性能
- 监控索引使用情况,删除不必要的索引
- 使用版本控制管理数据库结构变更
- 在生产环境执行DDL操作前先在测试环境验证
- 定期备份数据库结构
DDL操作注意事项:
- DDL操作通常需要表锁,可能影响数据库性能
- 在线DDL(MySQL 5.6+)可以减少锁的影响
- 在生产环境执行DDL前,评估其对业务的影响
- 考虑使用pt-online-schema-change等工具进行无锁表结构变更
- 记录所有DDL操作,便于审计和故障恢复
实际应用场景
电子商务系统表设计
SQL示例
-- 创建完整的电商数据库结构
CREATE DATABASE ecommerce
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
USE ecommerce;
-- 用户表
CREATE TABLE users (
user_id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
first_name VARCHAR(50),
last_name VARCHAR(50),
phone VARCHAR(20),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
last_login TIMESTAMP NULL,
is_active BOOLEAN DEFAULT TRUE,
INDEX idx_email (email),
INDEX idx_username (username),
INDEX idx_created_at (created_at)
);
-- 更多表定义...
下一步学习
掌握了数据定义语言后,您可以继续学习:
- 数据操作语言(DML) - 学习插入、更新和删除数据
- 约束 - 学习如何保证数据完整性
- 索引 - 深入学习索引原理和优化
- 性能优化 - 学习数据库性能调优技巧