MySQL SQL语句
一、基础必备:DDL 数据定义语句
1. 数据库操作
创建数据库(指定字符集+排序规则,避免中文乱码)
CREATE DATABASE IF NOT EXISTS test_db
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_unicode_ci;
查看所有数据库
SHOW DATABASES;
使用指定数据库
USE test_db;
删除数据库(谨慎操作!)
DROP DATABASE IF EXISTS test_db;
修改数据库字符集
ALTER DATABASE test_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
2. 数据表操作
创建用户表(含常用字段+索引)
CREATE TABLE IF NOT EXISTS `user` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`username` VARCHAR(50) NOT NULL COMMENT '用户名',
`password` VARCHAR(100) NOT NULL COMMENT '加密密码',
`phone` VARCHAR(20) DEFAULT NULL COMMENT '手机号',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态:1-正常 0-禁用',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_username` (`username`),
KEY `idx_phone` (`phone`),
KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户信息表';
查看表结构
DESC `user`;
查看建表语句
SHOW CREATE TABLE `user`;
修改表名
ALTER TABLE `user` RENAME TO `sys_user`;
添加字段(给用户表加邮箱字段)
ALTER TABLE `sys_user` ADD COLUMN `email` VARCHAR(100) DEFAULT NULL COMMENT '邮箱' AFTER `phone`;
修改字段(调整手机号字段长度)
ALTER TABLE `sys_user` MODIFY COLUMN `phone` VARCHAR(15) DEFAULT NULL COMMENT '手机号';
删除字段
ALTER TABLE `sys_user` DROP COLUMN `email`;
删除表
DROP TABLE IF EXISTS `sys_user`;
二、核心高频:DML 数据操作语句
1. 插入数据
基础插入(指定字段)
INSERT INTO `user` (username, password, phone)
VALUES ('zhangsan', 'e10adc3949ba59abbe56e057f20f883e', '13800138000');
批量插入(高效!推荐批量操作减少IO)
INSERT INTO `user` (username, password, phone)
VALUES
('lisi', 'e10adc3949ba59abbe56e057f20f883e', '13900139000'),
('wangwu', 'e10adc3949ba59abbe56e057f20f883e', '13700137000');
插入或更新(主键/唯一键冲突时更新)
INSERT INTO `user` (id, username, phone)
VALUES (1, 'zhangsan', '13800138001')
ON DUPLICATE KEY UPDATE phone = VALUES(phone);
2. 更新数据
基础更新(带WHERE条件,避免全表更新!)
UPDATE `user` SET phone = '13800138002' WHERE id = 1;
多字段更新
UPDATE `user`
SET phone = '13800138003', status = 0
WHERE username = 'zhangsan';
条件更新(仅更新创建时间早于2024年的用户状态)
UPDATE `user`
SET status = 0
WHERE create_time < '2024-01-01 00:00:00' AND status = 1;
3. 删除数据
条件删除(推荐!精准删除)
DELETE FROM `user` WHERE id = 3;
清空表(自增ID重置)
TRUNCATE TABLE `user`;
三、面试高频:DQL 数据查询语句
1. 基础查询
查询所有字段(生产环境避免*,指定字段更高效)
SELECT * FROM `user`;
查询指定字段
SELECT id, username, phone, create_time FROM `user`;
去重查询
SELECT DISTINCT phone FROM `user`;
条件查询(AND/OR/IN)
SELECT * FROM `user` WHERE status = 1 AND phone LIKE '138%';
SELECT * FROM `user` WHERE id IN (1,2,5);
排序(ASC升序,DESC降序)
SELECT * FROM `user` ORDER BY create_time DESC, id ASC;
分页查询(MySQL通用写法,offset从0开始)
-- 第1页:每页10条
SELECT * FROM `user` WHERE status = 1 ORDER BY id DESC LIMIT 0, 10;
-- 第2页
SELECT * FROM `user` WHERE status = 1 ORDER BY id DESC LIMIT 10, 10;
2. 聚合查询
统计总数
SELECT COUNT(*) AS total FROM `user` WHERE status = 1;
统计非空字段数
SELECT COUNT(phone) AS phone_count FROM `user`;
求和/平均值/最大值/最小值
SELECT
SUM(id) AS id_sum,
AVG(id) AS id_avg,
MAX(create_time) AS latest_time,
MIN(create_time) AS earliest_time
FROM `user`;
分组查询(GROUP BY + HAVING)
SELECT LEFT(phone, 3) AS phone_prefix, COUNT(*) AS num
FROM `user`
WHERE status = 1
GROUP BY phone_prefix
HAVING num > 1; -- 筛选分组后结果
3. 多表关联查询
先创建订单表用于关联示例
CREATE TABLE IF NOT EXISTS `order` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` BIGINT UNSIGNED NOT NULL,
`order_no` VARCHAR(32) NOT NULL,
`amount` DECIMAL(10,2) NOT NULL,
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';
INNER JOIN(内连接:只查匹配的数据)
SELECT u.username, o.order_no, o.amount
FROM `user` u
INNER JOIN `order` o ON u.id = o.user_id
WHERE u.status = 1;
LEFT JOIN(左连接:左表全查,右表无匹配则为NULL)
SELECT u.username, o.order_no, o.amount
FROM `user` u
LEFT JOIN `order` o ON u.id = o.user_id
ORDER BY u.id;
子查询(适用于简单场景,复杂场景推荐JOIN)
SELECT * FROM `user`
WHERE id IN (SELECT user_id FROM `order` WHERE amount > 100);
四、性能优化:常用 SQL 优化语句
sql
查看SQL执行计划(分析慢查询原因)
EXPLAIN SELECT * FROM `user` WHERE status = 1 ORDER BY create_time DESC LIMIT 0,10;
查看表索引
SHOW INDEX FROM `user`;
创建索引(针对慢查询字段)
CREATE INDEX idx_status_create_time ON `user` (status, create_time);
删除冗余索引
DROP INDEX idx_phone ON `user`;
优化表(修复碎片,仅MyISAM有效,InnoDB可忽略)
OPTIMIZE TABLE `user`;
查看慢查询日志状态
SHOW VARIABLES LIKE '%slow_query%';
开启慢查询日志(临时生效,重启失效)
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1; -- 记录执行时间>1秒的SQL
四、性能优化:常用 SQL 优化语句
查看SQL执行计划(分析慢查询原因)
EXPLAIN SELECT * FROM `user` WHERE status = 1 ORDER BY create_time DESC LIMIT 0,10;
查看表索引
SHOW INDEX FROM `user`;
创建索引(针对慢查询字段)
CREATE INDEX idx_status_create_time ON `user` (status, create_time);
删除冗余索引
DROP INDEX idx_phone ON `user`;
优化表(修复碎片,仅MyISAM有效,InnoDB可忽略)
OPTIMIZE TABLE `user`;
查看慢查询日志状态
SHOW VARIABLES LIKE '%slow_query%';
开启慢查询日志(临时生效,重启失效)
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1; -- 记录执行时间>1秒的SQL
五、实用技巧:常用函数
字符串函数
SELECT
CONCAT(username, '-', phone) AS user_info, -- 拼接
SUBSTRING(phone, 4, 4) AS phone_hide, -- 截取(第4位开始,取4位)
LENGTH(username) AS name_len, -- 长度
UPPER(username) AS name_upper -- 转大写
FROM `user`;
日期函数
SELECT
NOW() AS current_time, -- 当前时间(含时分秒)
DATE(create_time) AS create_date, -- 提取日期
DATE_ADD(create_time, INTERVAL 7 DAY) AS add_7day, -- 加7天
DATEDIFF(NOW(), create_time) AS diff_day -- 日期差(天)
FROM `user`;
条件函数
SELECT
id,
username,
CASE status
WHEN 1 THEN '正常'
WHEN 0 THEN '禁用'
ELSE '未知'
END AS status_text
FROM `user`;
六、注意事项
生产环境禁用 SELECT :指定字段可减少 IO 和网络传输,避免字段变更引发问题;
更新 / 删除必须加 WHERE:无 WHERE 条件会操作全表,可通过设置sql_safe_updates=1强制开启安全模式;
索引不是越多越好:过多索引会降低插入 / 更新效率,优先给查询高频字段建索引;
批量操作优先批量 SQL:单次批量插入 1000 条比 1000 次单条插入效率提升 10 倍以上;
字符集统一用 utf8mb4:兼容 emoji 表情,避免中文乱码。
总结
日常开发优先使用指定字段查询、批量操作、带条件的更新 / 删除,避免性能和数据安全问题;
多表查询优先用JOIN替代子查询,聚合查询结合GROUP BY + HAVING实现复杂统计;
优化慢查询先通过EXPLAIN分析执行计划,再针对性添加索引,避免冗余索引。