一、CRUD
1.1 是什么
CRUD 是一个常用的数据库操作的术语,它是英文单词 Create(创建)、Read(读取)、Update(更新)和Delete(删除)的首字母缩写,代表了数据库中基本的数据操作。
具体解释如下:
- Create(创建):在数据库中新增数据记录。使用 INSERT 语句来创建新的数据行,插入到表中。
- Read(读取):从数据库中检索数据记录。使用 SELECT 语句来查询表中的数据行,获取所需的数据。
- Update(更新):修改数据库中已存在的数据记录。使用 UPDATE 语句来更新表中的数据行,可以修改指定的字段值。
- Delete(删除):从数据库中删除数据记录。使用 DELETE 语句来删除表中的数据行,可以根据条件删除指定的数据。
CRUD 是开发和管理数据库系统常用的四种基本操作,它们涵盖了对数据库数据的创建、读取、更新和删除的操作。开发人员在使用数据库时经常执行这些操作来实现对数据的处理和管理。
1.2 讲解及实例
当涉及到数据库操作时,CRUD(Create, Read, Update, Delete)是一个常用的术语集合,代表了对数据库中数据的基本操作。下面详细解释每个操作并提供相关的示例:
1. Create(创建):
- 描述:在数据库中新增数据记录。
- SQL语句:INSERT INTO table_name (column1, column2, ...) VALUES (value1, value2, ...)
- 示例:假设有一个名为"users"的表,包含"id"和"name"两个列,我们想要插入一条新的用户记录。
INSERT INTO users (id, name) VALUES (1, 'John');
2. Read(读取):
- 描述:从数据库中检索数据记录。
- SQL语句:SELECT column1, column2, ... FROM table_name WHERE condition
- 示例:假设我们想要从名为"users"的表中检索所有用户的名字和年龄。
SELECT name, age FROM users;
3. Update(更新):
- 描述:修改数据库中已存在的数据记录。
- SQL语句:UPDATE table_name SET column1 = value1, column2 = value2, ... WHERE condition
- 示例:假设我们需要将名为"John"的用户的年龄更新为25岁。
UPDATE users SET age = 25 WHERE name = 'John';
4. Delete(删除):
- 描述:从数据库中删除数据记录。
- SQL语句:DELETE FROM table_name WHERE condition
- 示例:假设我们想要删除名为"John"的用户记录。
DELETE FROM users WHERE name = 'John';
这些示例展示了如何使用CRUD操作进行数据库处理。请注意,具体的SQL语句和条件将根据你的数据表结构和需求进行调整。CRUD操作是对数据库数据进行基本操作的核心,可以应用于各种场景和需求。
二、关键字
2.1 常用
MySQL 中常用的关键字包括(但不限于):
- 1. SELECT:用于从数据库中检索数据。
- 2. INSERT:用于向数据库表中插入新的数据行。
- 3. UPDATE:用于修改数据库表中已存在的数据行。
- 4. DELETE:用于从数据库表中删除数据行。
- 5. CREATE:用于创建数据库对象,如表、视图等。
- 6. ALTER:用于修改数据库对象的结构,如添加、修改、删除列等。
- 7. DROP:用于删除数据库对象,如表、视图等。
- 8. TRUNCATE:用于删除表中的所有数据行。
- 9. WHERE:用于设定条件,限定检索、更新或删除的数据行。
- 10. GROUP BY:用于对数据行进行分组计算。
- 11. ORDER BY:用于对查询结果进行排序。
- 12. JOIN:用于连接两个或多个表。
- 13. DISTINCT:用于返回不重复的结果集。
- 14. LIMIT:用于限制查询结果返回的行数。
- 15. IN:用于指定一个范围或一个可能的值列表。
- 16. LIKE:用于在查询中进行模糊匹配。
- 17. BETWEEN:用于指定一个范围。
- 18. AS:用于给列或表起别名。
- 19. UNION:用于合并两个或多个 SELECT 语句的结果集。
- 20. HAVING:用于在 GROUP BY 子句后进行过滤条件的设定。
这些关键字在 MySQL 中经常被使用,用于执行各种数据操作和查询。可以根据具体的需求和情况选择合适的关键字来完成数据库操作。
2.2 TRUNCATE
2.2.1 特点
TRUNCATE 是用于删除表中所有数据的关键字。它的主要特点包括:
- 快速操作:TRUNCATE 操作比 DELETE 操作更快,因为它是通过直接删除表中的数据页来实现的,而不是逐行删除数据。
- 删除所有数据:TRUNCATE 删除表中的所有数据行,但保留表的结构、约束、索引等信息。
- 归零自增计数器:TRUNCATE 还会将表的自增计数器(如 AUTO_INCREMENT)归零,下一次插入数据时会重新从初始值开始自增。
- 不记录日志:TRUNCATE 操作不会生成单独的删除日志记录,因此不会占用大量的事务日志空间。
2.2.2 注意事项
注意事项:
- 权限限制:只有具有 ALTER 权限的用户才能执行 TRUNCATE 操作。
- 不可回滚:TRUNCATE 操作是不可回滚的,一旦执行了 TRUNCATE,无法恢复被删除的数据。
- 无触发器和约束效果:TRUNCATE 操作会删除表中的所有数据,不会触发与数据行删除相关的触发器和约束条件,如外键约束、触发器等。
- 所有空间释放:TRUNCATE 操作将释放所有已分配给表的存储空间,即使之后再插入相同数量的数据,也不会使用之前已删除数据所占据的空间。
- 重新设置自增计数器:TRUNCATE 操作将重新设置表的自增计数器(如 AUTO_INCREMENT),下次插入数据时会从初始值开始自增。
- 注意相关表关系:如果删除表中的数据会破坏其他表的关系,应该谨慎使用 TRUNCATE,以免影响其他表的数据。
- 数据备份:在执行 TRUNCATE 操作之前,应该先做好表数据的备份,以防意外操作导致数据丢失。
这些是使用 TRUNCATE 操作时需要注意的事项,使用 TRUNCATE 可以快速删除表中的数据,但需要谨慎使用,避免不可恢复的数据丢失。
2.3 GROUP BY
2.2.1 特点
GROUP BY 是用于在 SELECT 查询中对结果进行分组的关键字。它的主要特点包括:
- 分组聚合:GROUP BY 将结果集按照指定的列或表达式进行分组,并对每个分组进行聚合计算,如求和、平均值、最大值等。
- 多个分组列:可以指定多个列或表达式作为分组条件,将结果集按照这些条件进行层级分组。
- 结果排序:分组后的结果并不是固定的顺序,可以通过使用 ORDER BY 对分组后的结果进行排序。
2.3.2 注意事项
注意事项:
- SELECT 表达式限制:GROUP BY 中的列或表达式必须是 SELECT 查询中的列或表达式之一,不允许使用别名或计算出的列。
- 聚合函数的使用:在 SELECT 查询中,除了分组的列或表达式外,其他的列必须使用聚合函数进行计算,或者出现在 GROUP BY 子句中。这是因为 GROUP BY 会将结果集分成多个分组,每个分组只能有一个聚合值。
- HAVING 子句:可以使用 HAVING 子句来对分组后的结果进行过滤。HAVING 与 WHERE 类似,但它用于针对分组后的结果集进行过滤。
- 效率考虑:GROUP BY 操作可能导致较大的计算量,尤其在处理大型数据集时。需要根据具体需求和性能要求来平衡使用 GROUP BY 的频率和效率。
- 数据完整性:使用 GROUP BY 前应确保分组的列或表达式的数据完整性,避免由于数据不完整导致的分组计算错误。
- NULL 值处理:在 GROUP BY 过程中,NULL 值通常会被当做一组进行处理,所以需要特别注意 NULL 值可能会产生的影响。
这些是使用 GROUP BY 时需要注意的事项,合理使用 GROUP BY 可以方便地对数据进行分组统计和分析。
2.4 ORDER BY
2.4.1 特点
ORDER BY 是用于对查询结果进行排序的关键字。它的主要特点包括:
- 排序结果:ORDER BY 关键字将查询结果按照指定的列或表达式进行排序,可以按升序(ASC)或降序(DESC)进行排列。
- 多个排序条件:可以指定多个列或表达式作为排序条件,用于实现多级排序,即在第一级排序相同的情况下,根据下一级排序条件进行排序。
- 字符排序:对于字符串数据,按照字典顺序(根据字符的 ASCII 码),从左到右进行排序。
- 数字排序:对于数字数据,按照数值的大小进行排序。
- NULL 值处理:在排序过程中,NULL 值通常被视为最小值或最大值,可以使用 NULLS FIRST 或 NULLS LAST 来控制 NULL 值的排序顺序。
2.4.2 注意事项
注意事项:
- SELECT 查询字段限制:ORDER BY 子句中的排序条件必须是 SELECT 查询中的列或表达式之一,不允许使用别名或计算出的列。
- 多级排序:可以根据需求指定多个排序条件,按照从左到右的顺序逐级排序。
- 字符串排序:对于字符串数据,字符的大小写通常有区分,可以使用合适的排序规则进行排序,如指定 COLLATE 子句。
- 排序方向:默认排序方向为升序(ASC),如果需要按降序排序,可以使用 DESC 关键字指定。
- 对排序结果进行限制:如果只需要查询前几行,可以使用 LIMIT 子句对排序结果进行限制,在排序之后再进行结果的截取。
- 性能考虑:对大型数据集进行排序可能会消耗较多的资源和时间,因此,需要根据具体情况和需求来平衡排序的频率和性能。
这些是使用 ORDER BY 子句时需要注意的事项,合理使用 ORDER BY 可以对查询结果进行排序,满足特定的排序需求。
2.5 HAVING
2.5.1 特点
HAVING 是一个用于在 SQL 查询中对分组结果进行过滤的关键字。它的主要特点包括:
- 分组过滤:HAVING 关键字用于在 GROUP BY 分组之后对分组结果进行过滤,只返回符合条件的分组。
- 聚合过滤:HAVING 条件可以使用聚合函数与比较运算符进行条件筛选,通常与 GROUP BY 一起使用,实现对分组后的聚合结果进行过滤。
- 类似于 WHERE:HAVING 类似于 WHERE 条件,但其中的条件是在 GROUP BY 分组后进行过滤。WHERE 用于在分组之前对行进行过滤,而 HAVING 用于在分组之后对分组结果进行过滤。
2.5.2 注意事项
注意事项:
- 使用条件表达式:HAVING 条件可以使用聚合函数、列名或其他的合法表达式。但要注意,HAVING 条件中不允许使用别名,需要直接引用相应的列或表达式。
- 聚合函数的使用:在 HAVING 条件中,通常使用聚合函数来比较和筛选分组结果。可以使用诸如 SUM、AVG、COUNT、MAX、MIN 之类的聚合函数。
- GROUP BY 子句:HAVING 通常与 GROUP BY 一起使用,因为 HAVING 是对分组结果进行过滤的,需要先进行分组操作。
- WHERE 与 HAVING 的区别:WHERE 用于在分组之前对行进行过滤,而 HAVING 用于在分组之后对分组结果进行过滤。通常情况下,应该尽量在 WHERE 条件中进行过滤,以减少要进行分组的数据量。
- 数据完整性:使用 HAVING 前应确保 GROUP BY 分组的列或表达式的数据完整性,避免由于数据不完整导致的分组计算错误。
- NULL 值处理:在 HAVING 条件中,NULL 值通常被视为一个分组,可以使用 IS NULL 或 IS NOT NULL 条件进行处理。
这些是使用 HAVING 条件时需要注意的事项,合理使用 HAVING 可以方便地对分组后的聚合结果进行过滤和筛选。
2.6 DELETE、DROP、TRUNCATE三者的区别
2.6.1 作用
在MySQL中,DELETE、DROP 和 TRUNCATE 是用于处理数据库对象(如表)的操作命令,它们有不同的作用和使用方式,区别如下:
1. DELETE:DELETE 用于从表中删除行数据,它是一种数据操作语言(DML)命令。DELETE 命令可以带有 WHERE 子句,用于指定删除的条件。DELETE 命令只删除表中的行数据,而不删除表本身。被删除的行数据可以通过使用事务回滚操作或备份进行恢复。同时,DELETE 语句也可以触发表上定义的触发器。
2. DROP:DROP 用于删除数据库对象,它是一种数据定义语言(DDL)命令。DROP 命令可以用于删除数据库、表、视图、索引、存储过程或函数等对象。被删除的对象及其相关的索引、触发器等信息都将被完全删除,无法恢复。在执行 DROP 命令之前,建议先备份相关数据或进行确认操作,以免误操作导致数据丢失。
3. TRUNCATE:TRUNCATE 用于删除表中的所有行数据,它是一种数据定义语言(DDL)命令。TRUNCATE 命令类似于 DELETE 命令,但是它更快速、更高效,因为它不是逐行删除数据,而是直接删除整个表的数据。TRUNCATE 命令也不触发表上定义的触发器,并且无法通过事务回滚操作来恢复被删除的数据。但是表的结构、索引、触发器等相关信息都保留。
总结一下:
- DELETE:删除表中的行数据,可以带有条件限制,可以回滚操作,触发触发器。
- DROP:删除整个数据库对象,如表、视图、存储过程等,删除后无法恢复。
- TRUNCATE:快速删除表中所有行数据,无法回滚操作,不触发触发器,保留表的结构和相关信息。
需要注意的是,DELETE 是针对行级操作,而 DROP 和 TRUNCATE 是针对表级操作。在使用这些命令时,务必小心,以避免误操作导致重要数据的丢失。
2.6.2 具体特点
具体特点的总结如下:
DELETE:
- 用于删除表中的行数据。
- 可以通过 WHERE 子句指定删除的条件。
- 可以回滚操作,即可以使用事务进行撤销操作。
- 可以触发表上定义的触发器。
DROP:
- 用于删除数据库对象,如表、视图、存储过程等。
- 删除后无法恢复,被删除的对象及其相关信息都被完全删除。
- 一定要谨慎使用,建议先备份相关数据或进行确认操作。
TRUNCATE:
- 用于快速删除表中的所有行数据。
- 不需要使用 WHERE 子句,直接删除整个表的数据。
- 无法回滚操作,即不可撤销。
- 不会触发表上定义的触发器。
- 保留表的结构和相关信息。
这些特点是基于 MySQL 数据库的操作命令 DELETE、DROP 和 TRUNCATE。在使用时,根据实际需求和操作目标选择适当的命令,同时要谨慎操作以避免数据丢失。
三、面试题
3.1 建立数据表
3.1.1 要求
-- 1.学生表-t_mysql_student
-- sid 学生编号,sname 学生姓名,sage 学生年龄,ssex 学生性别
-- 2.教师表-t_mysql_teacher
-- tid 教师编号,tname 教师名称
-- 3.课程表-t_mysql_course
-- cid 课程编号,cname 课程名称,tid 教师名称
-- 4.成绩表-t_mysql_score
-- sid 学生编号,cid 课程编号,score 成绩
3.1.2 代码
-- 学生表
insert into t_mysql_student values('01' , '赵雷' , '1990-01-01' , '男'); insert into t_mysql_student values('02' , '钱电' , '1990-12-21' , '男'); insert into t_mysql_student values('03' , '孙风' , '1990-12-20' , '男'); insert into t_mysql_student values('04' , '李云' , '1990-12-06' , '男'); insert into t_mysql_student values('05' , '周梅' , '1991-12-01' , '女'); insert into t_mysql_student values('06' , '吴兰' , '1992-01-01' , '女'); insert into t_mysql_student values('07' , '郑竹' , '1989-01-01' , '女'); insert into t_mysql_student values('09' , '张三' , '2017-12-20' , '女'); insert into t_mysql_student values('10' , '李四' , '2017-12-25' , '女'); insert into t_mysql_student values('11' , '李四' , '2012-06-06' , '女'); insert into t_mysql_student values('12' , '赵六' , '2013-06-13' , '女'); insert into t_mysql_student values('13' , '孙七' , '2014-06-01' , '女');
-- 教师表
insert into t_mysql_teacher values('01' , '张三'); insert into t_mysql_teacher values('02' , '李四'); insert into t_mysql_teacher values('03' , '王五');
-- 课程表
insert into t_mysql_course values('01' , '语文' , '02'); insert into t_mysql_course values('02' , '数学' , '01'); insert into t_mysql_course values('03' , '英语' , '03');
-- 成绩表
insert into t_mysql_score values('01' , '01' , 80); insert into t_mysql_score values('01' , '02' , 90); insert into t_mysql_score values('01' , '03' , 99); insert into t_mysql_score values('02' , '01' , 70); insert into t_mysql_score values('02' , '02' , 60); insert into t_mysql_score values('02' , '03' , 80); insert into t_mysql_score values('03' , '01' , 80); insert into t_mysql_score values('03' , '02' , 80); insert into t_mysql_score values('03' , '03' , 80); insert into t_mysql_score values('04' , '01' , 50); insert into t_mysql_score values('04' , '02' , 30); insert into t_mysql_score values('04' , '03' , 20); insert into t_mysql_score values('05' , '01' , 76); insert into t_mysql_score values('05' , '02' , 87); insert into t_mysql_score values('06' , '01' , 31); insert into t_mysql_score values('06' , '03' , 34); insert into t_mysql_score values('07' , '02' , 89); insert into t_mysql_score values('07' , '03' , 98);
3.2 试题
01)查询" 01 "课程比" 02 "课程成绩高的学生的信息及课程分数
解答的执行代码:
SELECT st.*, s1.score '01课程', s2.score '02课程' FROM ( SELECT * FROM t_mysql_score WHERE cid = "01" ) s1, ( SELECT * FROM t_mysql_score WHERE cid = "02" ) s2, t_mysql_student st WHERE s1.sid = s2.sid AND s1.sid = st.sid AND s1.score > s2.score
执行结果:
02)查询同时存在" 01 "课程和" 02 "课程的情况
解答的执行代码:
SELECT s.*, ( CASE WHEN s1.cid = "01" THEN s1.score END ) '01课程', ( CASE WHEN s2.cid = "02" THEN s1.score END ) '02课程' FROM ( SELECT * FROM t_mysql_score WHERE cid = "01" ) s1, ( SELECT * FROM t_mysql_score WHERE cid = "02" ) s2, t_mysql_student s WHERE s1.sid = s2.sid AND s1.sid = s.sid
执行结果:
03)查询存在" 01 "课程但可能不存在" 02 "课程的情况(不存在时显示为 null )
解答的执行代码:
SELECT s1.sid, s1.cid, s1.score '01课程', s2.score '02课程' FROM ( SELECT * FROM t_mysql_score sc WHERE sc.cid = "01" ) s1 LEFT JOIN ( SELECT * FROM t_mysql_score sc WHERE sc.cid = "02" ) s2 ON s1.sid = s2.sid
执行结果:
04)查询不存在" 01 "课程但存在" 02 "课程的情况
解答的执行代码:
SELECT * FROM t_mysql_score WHERE sid IN ( SELECT sid FROM t_mysql_student WHERE sid NOT IN ( SELECT sid FROM t_mysql_score WHERE cid = '01' ) ) AND cid = '02'
执行结果:
05)查询平均成绩大于等于 60 分的同学的学生编号和学生姓名和平均成绩
解答的执行代码:
SELECT s.sid, s.sname, ROUND( AVG( c.score ), 2 ) '平均成绩' FROM t_mysql_student s, t_mysql_score c WHERE s.sid = c.sid GROUP BY s.sid, s.sname HAVING avg( c.score ) >= 60
执行结果:
06)查询在t_mysql_score表存在成绩的学生信息
解答的执行代码:
SELECT s.* FROM t_mysql_score sc, t_mysql_student s WHERE sc.sid = s.sid GROUP BY s.sid
执行结果:
07)查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩(没成绩的显示为 null )
解答的执行代码:
SELECT s.sid, s.sname, count( sc.cid ) '选课总数', sum( sc.score ) '总成绩' FROM t_mysql_student s, t_mysql_score sc WHERE s.sid = sc.sid GROUP BY s.sid, s.sname
执行结果:
08)查询「李」姓老师的数量
解答的执行代码:
SELECT * FROM t_mysql_teacher t WHERE tname LIKE '李%'
执行结果:
09)查询学过「张三」老师授课的同学的信息
解答的执行代码:
SELECT * FROM t_mysql_student WHERE sid IN ( SELECT sc.sid FROM t_mysql_teacher t, t_mysql_score sc, t_mysql_course c WHERE t.tid = c.tid AND sc.cid = c.cid AND t.tname = "张三" GROUP BY sc.sid)
执行结果:
10)查询没有学全所有课程的同学的信息
解答的执行代码:
SELECT s.*, count( sc.score ) '课程数量' FROM t_mysql_student s, t_mysql_score sc WHERE s.sid = sc.sid GROUP BY s.sid, s.sname HAVING count( sc.score ) < ( SELECT count( 1 ) FROM t_mysql_course )
执行结果:
11)查询没学过"张三"老师讲授的任一门课程的学生姓名
解答的执行代码:
SELECT sname FROM t_mysql_student WHERE sid NOT IN ( SELECT sc.sid FROM t_mysql_score sc, t_mysql_course c, t_mysql_teacher t WHERE t.tid = c.tid AND sc.cid = c.cid AND t.tname = "张三" )
执行结果:
12)查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
解答的执行代码:
SELECT s.sid, s.sname, ROUND( AVG( sc.score ), 2 ) 平均成绩 FROM t_mysql_student s, t_mysql_score sc WHERE sc.sid = s.sid AND sc.score < 60 GROUP BY s.sid, s.sname HAVING count( sc.score ) >= 2
执行结果:
13)检索" 01 "课程分数小于 60,按分数降序排列的学生信息
解答的执行代码:
SELECT s.*, sc.score FROM t_mysql_student s, t_mysql_score sc WHERE s.sid = sc.sid AND sc.cid = "01" AND sc.score < 60 ORDER BY sc.score DESC
执行结果:
14)按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
解答的执行代码:
SELECT s.sid, s.sname, IF ( max( CASE WHEN sc.cid = '01' THEN sc.score END ) > 0, max( CASE WHEN sc.cid = '01' THEN sc.score END ), 0 ) 语文, IF ( max( CASE WHEN sc.cid = '02' THEN sc.score END ) > 0, max( CASE WHEN sc.cid = '02' THEN sc.score END ), 0 ) 数学, IF ( max( CASE WHEN sc.cid = '03' THEN sc.score END ) > 0, max( CASE WHEN sc.cid = '03' THEN sc.score END ), 0 ) 英语, ROUND( AVG( sc.score ), 2 ) 平均成绩 FROM t_mysql_student s, t_mysql_score sc WHERE s.sid = sc.sid GROUP BY s.sid, s.sname
执行结果:
15)查询各科成绩最高分、最低分和平均分:
以如下形式显示:课程 ID,课程 name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90
要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
解答的执行代码:
SELECT c.cid, c.cname, max( sc.score ) '最高分', min( sc.score ) '最低分', ROUND( AVG( sc.score ), 2 ) '平均分', CONCAT(ROUND(sum( IF ( sc.score >= 60, 1, 0 ) ) / COUNT( sc.score ) * 100,2 ),'%' ) 及格率, CONCAT(ROUND(sum( IF ( sc.score >= 70 AND sc.score < 80, 1, 0 ) ) / COUNT( sc.score ) * 100,2 ),'%' ) 中等率, CONCAT(ROUND(sum( IF ( sc.score >= 80 AND sc.score < 90, 1, 0 ) ) / COUNT( sc.score ) * 100,2 ),'%' ) 优良率, CONCAT(ROUND(sum( IF ( sc.score >= 90, 1, 0 ) ) / COUNT( sc.score ) * 100,2 ),'%' ) 优秀率, COUNT( sc.score ) 选修人数 FROM t_mysql_score sc, t_mysql_course c WHERE sc.cid = c.cid GROUP BY sc.cid ORDER BY 选修人数 DESC, c.cid ASC;
执行结果:
3.3 了解MySQL题的更多
点击文本内容即可查看更多知识