MySQL 基础语句
DDL 与 DML 核心操作
基础语句分为数据定义语言(DDL) 和数据操作语言(DML),前者负责表结构创建与修改,后者负责数据的增删改查,是所有数据库操作的基石。
1.1 DDL 语句:定义与管理表结构
DDL 语句主要包括CREATE
(创建)、ALTER
(修改)、DROP
(删除)、TRUNCATE
(清空),核心是对 “表结构” 而非 “数据” 操作。
1.1.1 1. 创建数据库与表(CREATE)
创建数据库:指定字符集与排序规则(避免中文乱码)
-- 创建数据库(若不存在),指定utf8mb4字符集(支持emoji)
CREATE DATABASE IF NOT EXISTS my_db
CHARACTER SET utf8mb4
COLLATE utf8mb4_general_ci;-- 切换到目标数据库
USE my_db;
创建表:需明确字段名、数据类型、约束(主键、非空、唯一等),以用户表(user)和订单表(order)为例:
-- 创建用户表(含主键、非空、唯一约束)
CREATE TABLE IF NOT EXISTS `user` (id INT PRIMARY KEY AUTO_INCREMENT COMMENT '用户ID(自增主键)',username VARCHAR(50) NOT NULL UNIQUE COMMENT '用户名(唯一,非空)',password VARCHAR(100) NOT NULL COMMENT '密码(加密存储)',phone CHAR(11) NOT NULL UNIQUE COMMENT '手机号(唯一,11位)',create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间(默认当前时间)',status TINYINT DEFAULT 1 COMMENT '状态:1-正常,0-禁用'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';-- 创建订单表(含外键约束,关联用户表)
CREATE TABLE IF NOT EXISTS `order` (order_id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '订单ID',user_id INT NOT NULL COMMENT '关联用户ID',order_amount DECIMAL(10,2) NOT NULL COMMENT '订单金额(保留2位小数)',order_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '下单时间',-- 外键约束:user_id关联user表的id,用户删除时禁止删除(RESTRICT)FOREIGN KEY (user_id) REFERENCES `user`(id) ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';
关键注意点:
- 表名 / 字段名用反引号(
)包裹,避免与MySQL关键字冲突(如
order` 是关键字); - 选择合适数据类型:手机号用
CHAR(11)
(固定长度),金额用DECIMAL
(避免浮点精度问题); - 必加
COMMENT
注释,方便后期维护; - 优先用
InnoDB
引擎(支持事务、外键),替代MyISAM
。
1.1.2 2. 修改表结构(ALTER)
日常开发中常需添加字段、修改字段类型或删除字段,核心语法如下:
-- 1. 给user表添加"邮箱"字段(允许为空)
ALTER TABLE `user`
ADD COLUMN email VARCHAR(100) NULL UNIQUE COMMENT '用户邮箱'
AFTER phone; -- 指定添加在phone字段后-- 2. 修改email字段为非空
ALTER TABLE `user`
MODIFY COLUMN email VARCHAR(100) NOT NULL COMMENT '用户邮箱(非空)';-- 3. 删除"状态"字段(谨慎操作,删除后数据不可恢复)
ALTER TABLE `user`
DROP COLUMN status;-- 4. 重命名表(将order表改为orders,避免关键字冲突)
ALTER TABLE `order`
RENAME TO orders;
1.1.3 3. 删除与清空表(DROP / TRUNCATE)
-- 1. 删除表(谨慎!删除表结构及所有数据,不可恢复)
DROP TABLE IF EXISTS orders;-- 2. 清空表(保留表结构,删除所有数据,自增主键重置为1)
TRUNCATE TABLE `user`;
DROP vs TRUNCATE 区别:
DROP
:删除表结构 + 数据,属于 DDL 操作,不可回滚;TRUNCATE
:仅删除数据,保留表结构,不可回滚,速度比DELETE FROM 表名
快(不记录日志)。
1.2 DML 语句:数据的增删改查
DML 语句是日常开发中最频繁使用的操作,核心是INSERT
(增)、DELETE
(删)、UPDATE
(改)、SELECT
(查)。
1.2.1 1. 插入数据(INSERT)
支持单条插入和批量插入,批量插入效率远高于单条循环插入。
-- 1. 单条插入(指定字段,推荐:字段顺序与值顺序对应)
INSERT INTO `user` (username, password, phone, email)
VALUES ('zhangsan', 'e10adc3949ba59abbe56e057f20f883e', '13800138000', 'zhangsan@xxx.com');-- 2. 批量插入(一次插入3条数据,减少IO交互)
INSERT INTO `user` (username, password, phone, email)
VALUES
('lisi', 'e10adc3949ba59abbe56e057f20f883e', '13900139000', 'lisi@xxx.com'),
('wangwu', 'e10adc3949ba59abbe56e057f20f883e', '13700137000', 'wangwu@xxx.com'),
('zhaoliu', 'e10adc3949ba59abbe56e057f20f883e', '13600136000', 'zhaoliu@xxx.com');-- 3. 从其他表查询并插入(将user表的部分数据插入到user_backup表)
INSERT INTO user_backup (username, phone, email)
SELECT username, phone, email FROM `user` WHERE id > 100;
1.2.2 2. 修改数据(UPDATE)
必须加WHERE
条件(否则全表修改!),支持多字段修改和关联子查询。
-- 1. 简单修改(将zhangsan的手机号改为13800138001)
UPDATE `user`
SET phone = '13800138001'
WHERE username = 'zhangsan';-- 2. 多字段修改(同时改手机号和邮箱)
UPDATE `user`
SET phone = '13800138002', email = 'zhangsan_new@xxx.com'
WHERE id = 1;-- 3. 关联子查询修改(将订单金额>1000的用户状态改为"高价值用户",假设user表有user_level字段)
UPDATE `user` u
INNER JOIN orders o ON u.id = o.user_id
SET u.user_level = 'high'
WHERE o.order_amount > 1000;
1.2.3 3. 删除数据(DELETE)
同样需加WHERE
条件(否则全表删除!),支持关联删除。
-- 1. 简单删除(删除手机号为13800138002的用户)
DELETE FROM `user`
WHERE phone = '13800138002';-- 2. 关联删除(删除没有任何订单的用户)
DELETE u FROM `user` u
LEFT JOIN orders o ON u.id = o.user_id
WHERE o.order_id IS NULL;
1.2.4 4. 查询数据(SELECT)
查询是 DML 中最复杂的操作,支持条件、排序、分组、分页、关联等,以下是高频场景示例:
1. 基础查询(字段筛选、条件过滤)
-- 1. 查询所有字段(不推荐,若表结构变更会报错,建议指定字段)
SELECT * FROM `user`;-- 2. 查询指定字段,加条件(查询id>2、状态正常的用户,只显示用户名和手机号)
SELECT username, phone
FROM `user`
WHERE id > 2 AND status = 1;-- 3. 模糊查询(查询手机号以138开头的用户)
SELECT username, phone
FROM `user`
WHERE phone LIKE '138%'; -- %匹配任意字符,_匹配单个字符
2. 排序与分页(ORDER BY / LIMIT)
-- 1. 按创建时间降序排序(最新的用户在前),取前10条
SELECT username, create_time
FROM `user`
ORDER BY create_time DESC
LIMIT 10;-- 2. 分页查询(第2页,每页10条:LIMIT 起始索引, 每页条数;起始索引=(页码-1)*每页条数)
SELECT username, phone
FROM `user`
ORDER BY id ASC
LIMIT 10, 10; -- 第2页,索引从10开始,取10条
3. 分组与聚合(GROUP BY / HAVING
常用于统计场景,如 “每个用户的订单总数”“订单金额大于 500 的用户”。
-- 1. 统计每个用户的订单总数(关联user和orders表)
SELECT u.username, COUNT(o.order_id) AS order_count
FROM `user` u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.username; -- GROUP BY需包含非聚合字段-- 2. 统计订单总数大于2、且平均订单金额>500的用户
SELECT u.username, COUNT(o.order_id) AS order_count,AVG(o.order_amount) AS avg_amount
FROM `user` u
INNER JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.username
HAVING order_count > 2 AND avg_amount > 500; -- HAVING过滤分组结果(WHERE过滤行)
4. 多表关联查询(JOIN)MySQL 支持 INNER JOIN(内连接)、LEFT JOIN(左连接)、RIGHT JOIN(右连接),核心是明确 “主表” 和 “关联条件”。
-- 左连接:查询所有用户,包括没有订单的用户(orders表字段为NULL)
SELECT u.username, o.order_id, o.order_amount
FROM `user` u
LEFT JOIN orders o ON u.id = o.user_id
ORDER BY u.id;-- 内连接:只查询有订单的用户(两表匹配才显示)
SELECT u.username, o.order_id, o.order_amount
FROM `user` u
INNER JOIN orders o ON u.id = o.user_id
WHERE o.order_time > '2024-01-01';