☰
MySQL基础操作与SQL分类详解
2026/11/6 7:16:42 网站建设 项目流程

1. MySQL基础操作与SQL分类解析

作为一名数据库开发工程师,我经常需要处理各种SQL查询和数据库管理任务。MySQL作为最流行的开源关系型数据库之一,掌握其基础操作是每个开发者的必备技能。让我们从最基础的连接和SQL分类开始。

1.1 客户端连接与基本操作

连接MySQL服务器是我们操作数据库的第一步。标准的连接命令如下:

mysql -uroot -h172.17.0.1 -P3306 -p123456

这个命令中:

  • -u指定用户名(这里是root)
  • -h指定主机地址(这里是172.17.0.1)
  • -P指定端口号(默认是3306)
  • -p后面跟着密码(这里是123456)

注意:在实际生产环境中,直接在命令行输入密码存在安全风险。更安全的做法是只输入-p参数而不带密码,系统会提示你单独输入密码。

连接成功后,我们可以执行一些基本操作:

-- 查看所有数据库 SHOW DATABASES; -- 查看当前使用的数据库 SELECT DATABASE(); -- 切换数据库 USE database_name;

1.2 SQL语言分类详解

SQL语言按照功能可以分为四大类,每类都有其特定的用途和语法:

DDL(数据定义语言)

用于定义和管理数据库对象(如表、索引、视图等)的结构。主要命令包括:

  • CREATE:创建数据库或表
  • ALTER:修改表结构
  • DROP:删除数据库或表
  • TRUNCATE:清空表数据(但保留表结构)

示例:

-- 创建数据库 CREATE DATABASE IF NOT EXISTS newdb DEFAULT CHARSET utf8mb4; -- 创建表 CREATE TABLE employee ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '编号', emp_id VARCHAR(10) COMMENT '员工工号', name VARCHAR(10) COMMENT '员工姓名' ) COMMENT '员工表';
DML(数据操作语言)

用于操作表中的数据。主要命令包括:

  • INSERT:插入新记录
  • UPDATE:更新现有记录
  • DELETE:删除记录

示例:

-- 插入数据 INSERT INTO employee(id, emp_id, name) VALUES (1,'00001','张三丰'); -- 更新数据 UPDATE employee SET name = '小昭' WHERE id = 1; -- 删除数据 DELETE FROM employee WHERE id = 1;
DQL(数据查询语言)

用于查询数据库中的数据。主要命令是SELECT及其各种变体。

DCL(数据控制语言)

用于控制数据库访问权限。主要命令包括:

  • GRANT:授予权限
  • REVOKE:撤销权限
  • CREATE USER:创建用户
  • ALTER USER:修改用户

2. 数据库与表操作实战

2.1 数据库的创建与管理

在实际项目中,我们通常需要创建多个数据库来隔离不同业务的数据。创建数据库时需要考虑字符集的选择:

-- 创建默认字符集的数据库 CREATE DATABASE IF NOT EXISTS itcast; -- 创建指定字符集的数据库(推荐使用utf8mb4以支持完整的Unicode字符) CREATE DATABASE IF NOT EXISTS itheima DEFAULT CHARSET utf8mb4;

经验分享:MySQL 5.7.7及以上版本中,utf8mb4是推荐的字符集,因为它支持完整的Unicode字符(包括emoji),而传统的utf8只支持基本的多语言平面字符。

删除数据库需要谨慎操作:

-- 删除数据库 DROP DATABASE itheima;

2.2 表结构的创建与修改

设计良好的表结构是数据库性能的基础。下面是一个完整的员工表创建示例:

CREATE TABLE employee ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '编号', emp_id VARCHAR(10) UNIQUE COMMENT '员工工号', name VARCHAR(10) NOT NULL COMMENT '员工姓名', gender CHAR(1) CHECK (gender IN ('男','女')) COMMENT '员工性别', age TINYINT UNSIGNED COMMENT '员工年龄', card_id CHAR(18) COMMENT '身份证号码', entrydate DATE COMMENT '入职时间' ) COMMENT '员工表' ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

表创建后,可能需要修改结构。常见的ALTER TABLE操作包括:

-- 添加新字段 ALTER TABLE employee ADD nickname VARCHAR(20) COMMENT '昵称'; -- 修改字段名和类型 ALTER TABLE employee CHANGE nickname username VARCHAR(30); -- 删除字段 ALTER TABLE employee DROP username; -- 重命名表 ALTER TABLE employee RENAME TO staff;

注意事项:在生产环境中修改大表结构可能会导致锁表,影响业务。建议在低峰期操作,或使用pt-online-schema-change等工具进行在线DDL操作。

3. 数据操作与查询技巧

3.1 数据的增删改操作

插入数据时,我们可以一次性插入多条记录以提高效率:

INSERT INTO employee(id, emp_id, name, gender, age, card_id, entrydate) VALUES (1,'00001','张三丰','男',63,'12345678987456321X','1987-10-10'), (2,'00002','张翠山','男',48,'123256789874563214','2011-1-19');

更新数据时,WHERE条件非常重要,否则会更新整张表:

-- 更新特定记录 UPDATE employee SET name = 'itheima' WHERE id = 1; -- 更新多个字段 UPDATE employee SET name = '小昭', gender = '女' WHERE id = 1; -- 批量更新(谨慎使用) UPDATE employee SET entrydate = '2008-01-01';

删除数据也有多种方式:

-- 条件删除 DELETE FROM employee WHERE gender = '女'; -- 清空表(可回滚) DELETE FROM employee; -- 清空表(不可回滚,重置自增ID) TRUNCATE TABLE employee;

3.2 基础查询与条件筛选

SELECT语句是SQL中最常用的命令,基本语法如下:

-- 查询特定字段 SELECT name, workaddress, age FROM employee; -- 查询所有字段(生产环境慎用) SELECT * FROM employee; -- 使用别名 SELECT workaddress AS '工作地址' FROM employee; -- 去重查询 SELECT DISTINCT workaddress FROM employee;

条件查询是SQL的核心功能之一:

-- 等值查询 SELECT * FROM employee WHERE age = 30; -- 范围查询 SELECT * FROM employee WHERE age BETWEEN 15 AND 20; -- 空值检查 SELECT * FROM employee WHERE card_id IS NULL; -- 多条件组合 SELECT * FROM employee WHERE gender = '女' AND age < 25; -- IN操作符 SELECT * FROM employee WHERE age IN (18,20,40);

3.3 模糊查询与通配符使用

模糊查询在业务中非常常见,主要使用LIKE操作符:

-- 查询姓名为两个字的员工 SELECT * FROM employee WHERE name LIKE '__'; -- 查询身份证号最后一位是X的员工 SELECT * FROM employee WHERE card_id LIKE '%X'; -- 查询姓张的员工 SELECT * FROM employee WHERE name LIKE '张%';

技巧:%匹配任意多个字符,_匹配单个字符。模糊查询通常会导致全表扫描,在大表上性能较差,应谨慎使用。

4. 高级查询与数据统计

4.1 聚合函数与分组统计

MySQL提供了多种聚合函数用于数据统计:

-- 计数 SELECT COUNT(*) FROM employee; -- 平均值 SELECT AVG(age) FROM employee; -- 最大值/最小值 SELECT MAX(age), MIN(age) FROM employee; -- 求和 SELECT SUM(age) FROM employee WHERE workaddress = '西安';

GROUP BY子句可以将数据分组后统计:

-- 按性别统计员工数量 SELECT gender, COUNT(*) FROM employee GROUP BY gender; -- 按性别统计平均年龄 SELECT gender, AVG(age) FROM employee GROUP BY gender; -- 多字段分组 SELECT workaddress, gender, COUNT(*) FROM employee GROUP BY workaddress, gender;

HAVING子句用于对分组结果进行筛选:

-- 查询员工数量大于等于3的工作地址 SELECT workaddress FROM employee WHERE age < 45 GROUP BY workaddress HAVING COUNT(workaddress) >= 3;

4.2 排序与分页查询

ORDER BY用于对结果排序:

-- 单字段排序 SELECT * FROM employee ORDER BY age; -- 多字段排序 SELECT * FROM employee ORDER BY age ASC, entrydate DESC;

LIMIT用于分页查询,是Web应用的常见需求:

-- 第一页,每页10条 SELECT * FROM employee LIMIT 0, 10; -- 第二页 SELECT * FROM employee LIMIT 10, 10; -- 通用分页公式:(页码-1)*每页记录数 SELECT * FROM employee LIMIT (page-1)*size, size;

4.3 复杂条件查询示例

结合前面学到的知识,我们可以构建更复杂的查询:

-- 查询性别为男,年龄20-40,姓名为三个字的员工 SELECT * FROM employee WHERE gender = '男' AND age BETWEEN 20 AND 40 AND name LIKE '___'; -- 查询年龄<=35的员工,按年龄升序、入职时间降序排序 SELECT name, age FROM employee WHERE age <= 35 ORDER BY age ASC, entrydate DESC; -- 查询性别为男,年龄20-40的前5个员工,按年龄和入职时间排序 SELECT * FROM employee WHERE gender = '男' AND age BETWEEN 20 AND 40 ORDER BY age, entrydate LIMIT 5;

5. 用户权限管理与高级功能

5.1 用户创建与权限控制

MySQL的权限系统非常精细,可以控制用户对数据库的各种操作:

-- 创建本地用户 CREATE USER itcast@'localhost' IDENTIFIED BY '123456'; -- 创建可从任意主机访问的用户 CREATE USER heima@'%' IDENTIFIED BY '123456'; -- 修改密码 ALTER USER heima@'%' IDENTIFIED BY '654321'; -- 删除用户 DROP USER itcast@'localhost';

权限授予与撤销:

-- 授予所有权限 GRANT ALL ON itcast.* TO heima@'%'; -- 撤销权限 REVOKE ALL ON itcast.* FROM heima@'%'; -- 查看权限 SHOW GRANTS FOR heima@'%';

安全建议:生产环境中应遵循最小权限原则,只授予用户必要的权限。避免使用具有全局权限的账户进行日常操作。

5.2 字符串与日期函数

MySQL提供了丰富的字符串处理函数:

-- 大小写转换 SELECT LOWER(card_id), UPPER(name) FROM employee; -- 字符串拼接 SELECT CONCAT(name, '(', age, ')') FROM employee; -- 填充字符串 SELECT LPAD(emp_id, 8, '0') FROM employee; -- 截取子串 SELECT SUBSTRING(card_id, 1, 6) FROM employee;

日期函数也非常实用:

-- 当前日期时间 SELECT CURDATE(), CURTIME(), NOW(); -- 日期部分提取 SELECT YEAR(entrydate), MONTH(entrydate), DAY(entrydate) FROM employee; -- 日期加减 SELECT DATE_ADD(entrydate, INTERVAL 1 YEAR) FROM employee; -- 日期差 SELECT DATEDIFF(NOW(), entrydate) AS days FROM employee; -- 计算入职天数并排序 SELECT name, DATEDIFF(NOW(), entrydate) AS days FROM employee ORDER BY days DESC;

5.3 条件判断与流程控制

CASE WHEN语句可以实现复杂的条件逻辑:

-- 简单条件判断 SELECT name, IF(age > 30, '资深', '新手') AS level FROM employee; -- 多条件判断 SELECT name, workaddress, CASE WHEN workaddress IN ('北京','上海','广州','深圳') THEN '一线城市' ELSE '二线城市' END AS city_level FROM employee; -- 工资等级分类 SELECT name, salary, CASE WHEN salary < 5000 THEN '普通员工' WHEN salary BETWEEN 5000 AND 9000 THEN '中层' ELSE '核心骨干' END AS salary_level FROM employee;

6. 表连接与子查询实战

6.1 内连接与外连接

表连接是关系型数据库的核心特性,允许我们从多个表中组合数据:

-- 隐式内连接 SELECT e.name, d.dept_name FROM employee e, department d WHERE e.dept_id = d.id; -- 显式内连接(推荐) SELECT e.name, d.dept_name FROM employee e INNER JOIN department d ON e.dept_id = d.id; -- 左外连接(保留左表所有记录) SELECT e.*, d.dept_name FROM employee e LEFT JOIN department d ON e.dept_id = d.id; -- 右外连接(保留右表所有记录) SELECT d.*, e.* FROM department d RIGHT JOIN employee e ON d.id = e.dept_id;

6.2 自连接查询

自连接是指表与自身连接,常用于查询层级关系:

-- 查询员工及其领导信息 SELECT e.name AS employee, m.name AS manager FROM employee e LEFT JOIN employee m ON e.manager_id = m.id;

6.3 子查询应用

子查询可以嵌套在SELECT、FROM、WHERE等子句中:

-- WHERE子句中的子查询 -- 查询比平均薪资高的员工 SELECT * FROM employee WHERE salary > (SELECT AVG(salary) FROM employee); -- 查询特定部门的员工 SELECT * FROM employee WHERE dept_id = (SELECT id FROM department WHERE dept_name = '研发部'); -- IN子查询 SELECT * FROM employee WHERE dept_id IN (SELECT id FROM department WHERE dept_name IN ('市场部','行政部')); -- FROM子句中的子查询 SELECT dept_id, avg_salary FROM ( SELECT dept_id, AVG(salary) AS avg_salary FROM employee GROUP BY dept_id ) AS dept_stats;

6.4 高级子查询技巧

-- 相关子查询:查询低于本部门平均工资的员工 SELECT e.* FROM employee e WHERE e.salary < ( SELECT AVG(salary) FROM employee WHERE dept_id = e.dept_id ); -- EXISTS子查询:查询有下属的员工 SELECT m.* FROM employee m WHERE EXISTS ( SELECT 1 FROM employee e WHERE e.manager_id = m.id ); -- 派生表连接:查询部门及员工数量 SELECT d.*, e_count.emp_count FROM department d LEFT JOIN ( SELECT dept_id, COUNT(*) AS emp_count FROM employee GROUP BY dept_id ) e_count ON d.id = e_count.dept_id;

7. 性能优化与最佳实践

7.1 索引使用建议

合理的索引可以大幅提高查询性能:

-- 创建索引 CREATE INDEX idx_employee_name ON employee(name); CREATE INDEX idx_employee_dept ON employee(dept_id); -- 多列索引 CREATE INDEX idx_employee_dept_age ON employee(dept_id, age); -- 查看索引 SHOW INDEX FROM employee;

经验法则:

  1. 为WHERE子句中的常用列创建索引
  2. 为JOIN条件的列创建索引
  3. 考虑为ORDER BY和GROUP BY的列创建索引
  4. 避免过度索引,因为索引会降低写入性能

7.2 EXPLAIN分析查询

使用EXPLAIN可以分析查询执行计划:

EXPLAIN SELECT * FROM employee WHERE name = '张三丰';

重点关注:

  • type:最好能达到ref或range级别,避免ALL(全表扫描)
  • possible_keys:可能使用的索引
  • key:实际使用的索引
  • rows:预估需要检查的行数

7.3 查询优化技巧

  1. **避免SELECT ***:只查询需要的列
  2. 合理使用JOIN:小表驱动大表
  3. LIMIT分页优化:对于大表分页,避免使用大偏移量
    -- 低效写法(偏移量大时性能差) SELECT * FROM employee LIMIT 10000, 20; -- 优化写法(使用索引列过滤) SELECT * FROM employee WHERE id > 10000 LIMIT 20;
  4. 批量操作:使用批量INSERT代替单条插入
  5. 避免在索引列上使用函数:这会导致索引失效
    -- 索引失效的写法 SELECT * FROM employee WHERE YEAR(entrydate) = 2020; -- 优化写法 SELECT * FROM employee WHERE entrydate BETWEEN '2020-01-01' AND '2020-12-31';

7.4 事务与锁定

MySQL默认使用自动提交模式,但有时需要显式使用事务:

-- 开始事务 START TRANSACTION; -- 执行一系列操作 UPDATE account SET balance = balance - 100 WHERE id = 1; UPDATE account SET balance = balance + 100 WHERE id = 2; -- 提交或回滚 COMMIT; -- 或 ROLLBACK;

注意事项:

  1. 事务应尽量短小,避免长时间持有锁
  2. 合理设置隔离级别(默认REPEATABLE READ)
  3. 注意死锁问题,多个事务以相同顺序访问资源

8. 实际业务场景解决方案

8.1 员工管理系统查询示例

-- 查询各部门人数及平均工资 SELECT d.dept_name, COUNT(e.id) AS employee_count, IFNULL(AVG(e.salary), 0) AS avg_salary FROM department d LEFT JOIN employee e ON d.id = e.dept_id GROUP BY d.id ORDER BY employee_count DESC; -- 查询各部门工资最高的员工 SELECT d.dept_name, e.name, e.salary FROM department d JOIN employee e ON e.id = ( SELECT id FROM employee WHERE dept_id = d.id ORDER BY salary DESC LIMIT 1 ); -- 查询工资高于部门平均工资的员工 SELECT e.* FROM employee e WHERE e.salary > ( SELECT AVG(salary) FROM employee WHERE dept_id = e.dept_id );

8.2 层级数据查询

处理组织结构等层级数据时,可以使用递归查询(MySQL 8.0+):

-- 使用CTE递归查询组织层级 WITH RECURSIVE org_tree AS ( -- 基础查询:顶级部门 SELECT id, dept_name, parent_id, 1 AS level FROM department WHERE parent_id IS NULL UNION ALL -- 递归查询:子部门 SELECT d.id, d.dept_name, d.parent_id, ot.level + 1 FROM department d JOIN org_tree ot ON d.parent_id = ot.id ) SELECT * FROM org_tree ORDER BY level, id;

8.3 数据统计与报表

-- 月度入职统计 SELECT YEAR(entrydate) AS year, MONTH(entrydate) AS month, COUNT(*) AS new_employees, AVG(age) AS avg_age FROM employee GROUP BY YEAR(entrydate), MONTH(entrydate) ORDER BY year, month; -- 员工年龄分布 SELECT CASE WHEN age < 20 THEN '20岁以下' WHEN age BETWEEN 20 AND 29 THEN '20-29岁' WHEN age BETWEEN 30 AND 39 THEN '30-39岁' ELSE '40岁及以上' END AS age_group, COUNT(*) AS count, ROUND(COUNT(*) * 100.0 / (SELECT COUNT(*) FROM employee), 2) AS percentage FROM employee GROUP BY age_group ORDER BY MIN(age);

9. 常见问题与解决方案

9.1 性能问题排查

  1. 慢查询日志分析:

    -- 查看慢查询配置 SHOW VARIABLES LIKE 'slow_query%'; -- 临时开启慢查询日志 SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 1; -- 超过1秒的查询
  2. 锁等待问题:

    -- 查看当前锁等待 SHOW ENGINE INNODB STATUS; -- 查看正在运行的进程 SHOW PROCESSLIST;

9.2 数据一致性问题

  1. 使用事务保证一致性:

    START TRANSACTION; -- 扣除A账户金额 UPDATE accounts SET balance = balance - 100 WHERE id = 1; -- 增加B账户金额 UPDATE accounts SET balance = balance + 100 WHERE id = 2; COMMIT;
  2. 外键约束:

    -- 添加外键约束 ALTER TABLE employee ADD CONSTRAINT fk_employee_department FOREIGN KEY (dept_id) REFERENCES department(id) ON DELETE RESTRICT ON UPDATE CASCADE;

9.3 备份与恢复

  1. 使用mysqldump备份:

    mysqldump -u root -p database_name > backup.sql
  2. 恢复备份:

    mysql -u root -p database_name < backup.sql
  3. 二进制日志恢复:

    -- 查看二进制日志状态 SHOW BINARY LOGS; -- 从特定位置恢复 mysqlbinlog --start-position=4 --stop-position=106 /var/log/mysql/mysql-bin.000001 | mysql -u root -p

10. 进阶学习建议

掌握了这100个SQL练习题后,建议进一步学习以下内容:

  1. MySQL高级特性:

    • 存储过程和函数
    • 触发器
    • 视图
    • 事件调度器
  2. 性能优化:

    • 索引优化策略
    • 查询执行计划分析
    • 服务器参数调优
  3. 高可用架构:

    • 主从复制
    • 读写分离
    • 集群部署
  4. 替代方案:

    • MySQL 8.0新特性
    • 其他关系型数据库(PostgreSQL等)
    • NoSQL数据库(MongoDB、Redis等)

在实际工作中,我发现很多性能问题都源于不合理的SQL写法。建议定期审查慢查询日志,对高频查询进行优化。同时,随着数据量增长,要考虑分库分表策略,避免单表过大导致的性能瓶颈。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询