数据库MySQL-(初阶)Create(创建/新增)、Retrieve(读取/查询)、Update(更新/修改)、Delete(删除)

王者杯·14天创作挑战营·第5期 10w+人浏览 949人参与

好的,我们来详细解析一下您提供的图片中关于 MySQL 基础的增删改查(CRUD)操作。我将严格按照图片中的大纲结构,对每一个知识点进行详尽的解释,并为所有SQL代码提供逐行注释,同时进行深入的扩展说明,以确保内容详实、易于理解,并达到您要求的篇幅。


引言:什么是CRUD?

在正式开始之前,我们首先要理解 CRUD 这个核心概念。正如第一张图片所示,CRUD 是四个英文单词的首字母缩写,它们构成了数据库操作最核心、最基础的四个功能:

  • C: Create(创建/新增):在数据库的表中创建新的记录。对应 SQL 中的 INSERT 语句。

  • R: Retrieve(读取/查询):从数据库的表中读取一条或多条记录。对应 SQL 中的 SELECT 语句,这是最复杂、最常用的一部分。

  • U: Update(更新/修改):修改数据库表中已存在的记录。对应 SQL 中的 UPDATE 语句。

  • D: Delete(删除):从数据库表中删除一条或多条记录。对应 SQL 中的 DELETE 语句。

这四个操作是我们与数据库进行交互的基石。无论是开发一个复杂的企业级应用,还是一个简单的个人网站,其后台数据处理都离不开对数据的增、删、改、查。掌握了 CRUD,就等于掌握了与数据库对话的基本语言。

准备工作:创建示例数据表

为了让后续的示例代码能够实际运行并更具象化,我们首先需要创建一个用于演示的数据库和表。假设我们正在为一个学校管理系统设计数据库,我们来创建一个 students 表。

SQL

-- 如果名为 school 的数据库不存在,则创建它
CREATE DATABASE IF NOT EXISTS school;

-- 切换到 school 数据库上下文
USE school;

-- 如果名为 students 的表已存在,则先删除它,方便我们重新创建
DROP TABLE IF EXISTS students;

-- 创建一个名为 students 的表,用于存储学生信息
CREATE TABLE students (
    id INT PRIMARY KEY AUTO_INCREMENT,  -- 学生ID,整数类型,主键,并且自增长
    student_no VARCHAR(20) NOT NULL UNIQUE, -- 学号,字符串类型,不允许为空,且必须唯一
    name VARCHAR(50) NOT NULL,          -- 姓名,字符串类型,不允许为空
    gender VARCHAR(2) DEFAULT '未知',     -- 性别,字符串类型,默认为 '未知'
    age INT,                            -- 年龄,整数类型
    score DECIMAL(5, 2),                -- 成绩,十进制数,总共5位,小数点后2位
    enrollment_date DATE                -- 入学日期,日期类型
);

知识点解析与扩展:

  • CREATE DATABASE IF NOT EXISTS school;: 这是一个健壮的写法,IF NOT EXISTS 可以防止在数据库已经存在时执行 CREATE DATABASE 导致的错误。

  • USE school;: 这个命令用于将当前的会话环境切换到指定的数据库,后续的所有表操作都将默认在该数据库下进行。

  • CREATE TABLE students (...): 定义表的结构。

    • INT: 整数类型。

    • VARCHAR(N): 可变长度的字符串,N 是最大字符数。

    • DECIMAL(P, S): 精确的十进制数类型,P是总位数,S是小数位数。非常适合存储金额、分数等需要精确计算的数值,可以避免浮点数(FLOAT, DOUBLE)的精度问题。

    • DATE: 只存储日期(年-月-日)。

    • PRIMARY KEY: 主键。表中每一行数据的唯一标识符。一个表只能有一个主键。主键列的值必须是唯一的(UNIQUE)且不能为空(NOT NULL)。

    • AUTO_INCREMENT: 自增长。通常用于主键列,当我们插入新数据时,如果未指定该列的值,数据库会自动为其分配一个比当前最大值大1的唯一数字。

    • NOT NULL: 非空约束。规定该列在插入或更新时必须有一个值。

    • UNIQUE: 唯一约束。规定该列的所有值必须是唯一的,不能有重复。

    • DEFAULT '未知': 默认值约束。如果在插入新数据时没有为该列提供值,数据库会自动使用这个默认值。

现在,我们有了一个空的 students 表,可以开始学习 CRUD 操作了。


二、 新增数据 (Create)

新增数据就是向数据表中插入一行或多行新的记录。我们使用 INSERT INTO 语句。

2.1 单行数据 + 全列插入

这是最基础的插入方式,需要为表中的每一列都提供一个值,并且值的顺序必须与表中列的定义顺序完全一致。

语法:

INSERT INTO 表名 VALUES (值1, 值2, ..., 值N);

示例:

SQL

-- 向 students 表中插入一条完整的学生记录
INSERT INTO students VALUES (
    NULL,           -- 对应 id 列。因为它是 AUTO_INCREMENT,所以可以填 NULL,系统会自动生成
    'SN2025001',    -- 对应 student_no 列
    '张三',         -- 对应 name 列
    '男',           -- 对应 gender 列
    18,             -- 对应 age 列
    95.50,          -- 对应 score 列
    '2025-09-01'    -- 对应 enrollment_date 列
);

逐行注释与解析:

  1. INSERT INTO students VALUES (...): INSERT INTO 是SQL中用于插入数据的关键字,students 是目标表名,VALUES 后面跟着包含具体值的括号。

  2. NULL: 我们为 id 列提供了 NULL。因为 id 被定义为 PRIMARY KEY AUTO_INCREMENT,数据库会自动忽略这个 NULL,并生成一个唯一的、自增的ID(在这里会是1)。我们也可以完全不写 id 列,但这需要使用“指定列插入”的方式。

  3. 'SN2025001', '张三', '男': 这些是字符串类型的值,在SQL中必须用单引号 ' 或双引号 " 包围。

  4. 18, 95.50: 这些是数值类型,可以直接写入,无需引号。

  5. '2025-09-01': 日期类型在SQL中通常也以字符串的形式提供,格式为 'YYYY-MM-DD'

深入扩展与注意事项:

  • 风险:全列插入非常不健壮。如果未来数据库表的结构发生了改变(例如,增加了一个新列、删除了一个列或调整了列的顺序),那么这条 INSERT 语句就会立刻报错或插入错误的数据。因此,在实际项目开发中,强烈不推荐使用这种写法。

  • 值的匹配:值的数量必须与表的列数完全匹配,值的类型也必须与对应列的数据类型兼容(例如,不能把一个字符串插入到 INT 类型的列中)。

2.2 多行数据 + 指定列插入

这是一种更常用、更安全、更灵活的插入方式。我们可以明确指定要为哪些列插入数据,并且可以一次性插入多条记录。

语法:

INSERT INTO 表名 (列1, 列2, ...) VALUES (值1A, 值2A, ...), (值1B, 值2B, ...), ...;

示例:

SQL

-- 向 students 表中一次性插入三条新的学生记录,并指定要插入的列
INSERT INTO students (student_no, name, age, score, enrollment_date, gender) 
VALUES 
    ('SN2025002', '李四', 19, 88.00, '2025-09-01', '男'), -- 第一条记录
    ('SN2025003', '王五', 18, 92.50, '2025-09-02', '女'), -- 第二条记录
    ('SN2025004', '赵六', 20, 76.00, '2025-09-01', '男'); -- 第三条记录

逐行注释与解析:

  1. INSERT INTO students (student_no, name, ...): 在表名后面,我们用括号明确列出了要插入数据的列名。这样做的好处是,列的顺序可以任意,不一定非要和表定义的顺序一致。

  2. VALUES (...): VALUES 关键字后面跟着每一行的数据。

  3. ('SN2025002', ...): 每一行的数据都用一对括号包围,里面的值的顺序必须与前面指定的列名顺序 (student_no, name, ...) 一一对应。

  4. ,: 多行数据之间用逗号隔开。

示例2:插入时使用默认值

我们没有为 gender 列提供值,它将使用我们建表时设置的 DEFAULT '未知'。

SQL

-- 插入一条记录,但不指定 gender,让其使用默认值
INSERT INTO students (student_no, name, age, score, enrollment_date)
VALUES
    ('SN2025005', '孙七', 19, 85.00, '2025-09-03');

这条语句执行后,孙七 同学的 gender 字段会被自动设为 '未知'

深入扩展与注意事项:

  • 健壮性:指定列插入是推荐的最佳实践。即使表结构未来增加了新的列(只要新列允许为NULL或有默认值),这条语句依然可以正常工作。

  • 性能:一次性插入多行数据(如上例)比执行多次单行插入的 INSERT 语句效率要高得多。这是因为数据库只需要解析一次SQL,并进行一次事务提交,减少了网络往返和数据库的开销。

  • INSERT IGNORE:如果插入的数据会导致唯一键(UNIQUEPRIMARY KEY)冲突,普通的 INSERT 语句会报错。如果使用 INSERT IGNORE INTO ...,数据库会忽略这些会导致冲突的行,不报错,并继续插入其他合法的行。

  • INSERT ... ON DUPLICATE KEY UPDATE ...:这是一个非常有用的扩展,常被称为 "UPSERT" (Update or Insert)。当插入的数据导致唯一键冲突时,它不会报错,而是会执行 UPDATE 子句来更新已存在的那一行。例如:INSERT INTO students (student_no, name) VALUES ('SN2025001', '张三丰') ON DUPLICATE KEY UPDATE name = '张三丰'; 如果学号 SN2025001 已存在,它会把该学生的姓名更新为“张三丰”。


三、 查询数据 (Retrieve)

查询是数据库操作中使用最频繁、功能最强大的部分。我们使用 SELECT 语句来从表中检索数据。

3.1 全列查询

查询出表中的所有列和所有行的数据。

语法:

SELECT * FROM 表名;

示例:

SQL

-- 从 students 表中查询出所有学生的所有信息
SELECT * FROM students;

逐行注释与解析:

  1. SELECT *: SELECT 是查询关键字。星号 * 是一个通配符,代表“所有列”。

  2. FROM students: FROM 关键字用于指定要从哪个表中查询数据,这里是 students 表。

深入扩展与注意事项:

  • 性能问题:在生产环境中,应极力避免使用 SELECT *。原因有:

    1. 不必要的网络开销:它会查询出所有列的数据,即使你只关心其中几列。当表很大,或者有 TEXTBLOB 等大字段时,会传输大量无用数据,占用网络带宽。

    2. 可读性和维护性差:代码的阅读者无法立即知道这个查询到底需要哪些字段。

    3. 潜在的错误:如果应用程序依赖于列的固定顺序,而数据库表的列顺序被修改,SELECT * 返回的列顺序也可能改变,导致程序出错。

  • 适用场景SELECT * 主要用于临时的数据探查和调试,或者当表很小且确实需要所有列时。

3.2 指定列查询

只查询你所需要的特定列,这是推荐的做法。

语法:

SELECT 列1, 列2, ... FROM 表名;

示例:

SQL

-- 从 students 表中只查询所有学生的学号和姓名
SELECT student_no, name FROM students;

逐行注释与解析:

  1. SELECT student_no, name: 在 SELECT 后面明确列出需要查询的列名,多个列名之间用逗号隔开。

  2. FROM students: 指定数据来源是 students 表。

这种方式清晰、高效,是编写查询语句的标准实践。

3.3 查询字段为表达式

我们不仅可以查询原始的列数据,还可以对列数据进行计算和处理,将计算结果作为一个新的列返回。

语法:

SELECT 表达式1, 表达式2, ... FROM 表名;

示例:

SQL

-- 查询所有学生的姓名,以及他们当前分数提高10%后的理论分数
SELECT name, score * 1.1 FROM students;

逐行注释与解析:

  1. SELECT name, score * 1.1: 我们查询了 name 列,同时查询了一个表达式 score * 1.1。MySQL会对每一行数据的 score 值乘以1.1,并将结果作为第二列返回。

深入扩展与注意事项:

  • 表达式类型:表达式可以是任何有效的计算,包括:

    • 算术运算+, -, *, / (例如 score + 5)

    • 字符串函数CONCAT(name, '(', student_no, ')') 可以将姓名和学号拼接成一个字符串。

    • 日期函数YEAR(enrollment_date)可以提取入学年份。

    • 逻辑运算:在CASE语句中使用。

  • 不影响原数据:查询中的表达式不会修改表里存储的原始数据。它只是在查询结果集中动态计算出一个新值。

3.4 别名 (Alias)

当查询的列名很长、或者是一个复杂的表达式时,返回的结果集中的列名会不直观。我们可以使用别名来给结果集中的列重命名。

语法:

SELECT 列 [AS] 别名1, 表达式 [AS] 别名2, ... FROM 表名; (AS 关键字可以省略)

示例:

SQL

-- 查询学生的姓名和分数,并将结果集中的列名显示为中文
SELECT 
    name AS '姓名',       -- 为 name 列指定别名 '姓名'
    score AS '成绩'      -- 为 score 列指定别名 '成绩'
FROM 
    students;

示例2:为表达式设置别名

SQL

-- 查询学生姓名和提高10%后的分数,并为表达式结果列指定一个有意义的别名
SELECT 
    name,                       -- 查询原始的姓名列
    score * 1.1 AS bonus_score -- 为 score * 1.1 这个表达式的结果指定别名 bonus_score
FROM 
    students;

深入扩展与注意事项:

  • AS 关键字:在列别名中,AS 通常可以省略,如 SELECT name '姓名' FROM students;。但为了代码的可读性,强烈建议总是写上 AS

  • 表别名:别名不仅可以用于列,也可以用于表,这在多表连接查询(JOIN)中至关重要。例如:SELECT s.name FROM students AS s;

3.5 去重: DISTINCT

使用 DISTINCT 关键字可以从查询结果中移除重复的行。

语法:

SELECT DISTINCT 列1, 列2, ... FROM 表名;

示例:

SQL

-- 查询我们的学生都来自哪些性别
SELECT DISTINCT gender FROM students;

逐行注释与解析:

  1. SELECT DISTINCT gender: DISTINCT 关键字作用于其后的所有列。这条语句会返回 students 表中 gender 列的所有唯一值。如果表中有'男', '女', '男', '未知',结果将是 '男', '女', '未知' 三行。

深入扩展与注意事项:

  • 作用于整行DISTINCT 作用于整个 SELECT 的列列表,而不是单个列。例如,SELECT DISTINCT gender, age FROM students; 会返回唯一的 (gender, age) 组合。如果存在 ('男', 18)('男', 19) 两条记录,它们都会被返回,因为它们的组合是不同的。

3.6 排序: ORDER BY

使用 ORDER BY 子句可以对查询结果进行排序。

语法:

SELECT ... FROM ... ORDER BY 列1 [ASC|DESC], 列2 [ASC|DESC], ...;

示例1:单列排序

SQL

-- 查询所有学生信息,并按照成绩从高到低进行排序
SELECT name, score 
FROM students 
ORDER BY score DESC;

示例2:多列排序

SQL

-- 查询所有学生信息,优先按照成绩从高到低排序,如果成绩相同,则按照年龄从小到大排序
SELECT name, score, age
FROM students
ORDER BY score DESC, age ASC;

逐行注释与解析:

  1. ORDER BY score DESC: ORDER BY 是排序子句。score 是排序依据的列。DESC (Descending)表示降序(从大到小)。

  2. ASC (Ascending) 表示升序(从小到大),这是默认的排序方式,所以 ORDER BY age ASCORDER BY age 是等价的。

  3. ORDER BY score DESC, age ASC: 当进行多列排序时,数据库会首先按照第一个条件 (score DESC) 排序。只有当第一列的值相同时,才会启用第二个排序条件 (age ASC) 对这些成绩相同的行进行内部排序。

深入扩展与注意事项:

  • NULL 值的排序:在MySQL中,ORDER BY ... ASC 会将 NULL 值排在最前面,ORDER BY ... DESC 会将 NULL 值排在最后面。

  • 性能:对大数据集进行排序是一项非常耗费资源的操作,特别是当排序的列没有索引时,可能会导致性能问题。应尽量为经常用于排序的列创建索引。

3.7 条件查询: WHERE

WHERE 子句用于从表中筛选出满足指定条件的记录。这是 SELECT 语句的精髓所在。

语法:

SELECT ... FROM ... WHERE 条件;

WHERE 子句中常用的运算符:

  1. 比较运算符: > (大于), < (小于), >= (大于等于), <= (小于等于), = (等于), !=<> (不等于)。

    SQL

    -- 查询成绩大于90分的学生
    SELECT name, score FROM students WHERE score > 90;
    
    -- 查询姓名不叫“张三”的学生
    SELECT name, student_no FROM students WHERE name != '张三';
    
  2. BETWEEN ... AND ...: 用于筛选某个范围内的值(包含边界)。

    SQL

    -- 查询年龄在18到20岁之间的学生(包括18和20岁)
    SELECT name, age FROM students WHERE age BETWEEN 18 AND 20;
    -- 上一句等价于: SELECT name, age FROM students WHERE age >= 18 AND age <= 20;
    
  3. IN (...): 筛选出列的值在指定列表中的记录。

    SQL

    -- 查询姓名为“张三”或“李四”的学生
    SELECT * FROM students WHERE name IN ('张三', '李四');
    -- 上一句等价于: SELECT * FROM students WHERE name = '张三' OR name = '李四';
    -- 当列表很长时,IN 的写法更简洁。
    
  4. IS NULL / IS NOT NULL: 判断列的值是否为 NULL

    SQL

    -- 假设有些学生没有录入年龄,查询这些学生
    -- INSERT INTO students (student_no, name) VALUES ('SN2025006', '钱八'); -- 先插入一条年龄为NULL的数据
    SELECT name FROM students WHERE age IS NULL;
    
    -- 查询所有已经录入了年龄的学生
    SELECT name, age FROM students WHERE age IS NOT NULL;
    

    特别注意:不能使用 = NULL!= NULL 来判断 NULL 值。NULL 是一个特殊的值,代表“未知”或“不存在”,它不等于任何值,包括它自己。因此必须使用 IS NULLIS NOT NULL

  5. LIKE: 用于模糊查询,通常与通配符一起使用。

    • %: 代表零个、一个或多个任意字符。

    • _: 代表一个任意字符。

    SQL

    -- 查询所有姓“张”的学生
    SELECT name FROM students WHERE name LIKE '张%'; -- '张'开头,后面可以是任意字符
    
    -- 查询名字中包含“五”的学生
    SELECT name FROM students WHERE name LIKE '%五%'; -- 前后都可以是任意字符
    
    -- 查询名字是两个字且第二个字是“六”的学生
    SELECT name FROM students WHERE name LIKE '_六'; -- 第一个字符是任意单个字符,第二个是'六'
    
  6. 逻辑运算符: AND (与), OR (或), NOT (非),用于连接多个条件。

    SQL

    -- 查询年龄大于18岁 并且 成绩大于90分的学生
    SELECT name, age, score FROM students WHERE age > 18 AND score > 90;
    
    -- 查询年龄大于19岁 或者 性别为“女”的学生
    SELECT name, age, gender FROM students WHERE age > 19 OR gender = '女';
    
    -- 查询学号不是以 'SN2025001' 开头的学生
    SELECT name, student_no FROM students WHERE NOT (student_no LIKE 'SN2025001%');
    

深入扩展与注意事项:

  • 运算符优先级NOT 的优先级最高,然后是 AND,最后是 OR。当一个 WHERE 子句中同时包含 ANDOR 时,为避免歧义和逻辑错误,强烈建议使用括号 () 来明确指定条件的组合顺序。例如:WHERE (age > 19 AND gender = '男') OR score > 95;

  • 索引对WHERE的影响WHERE 子句是数据库查询优化的核心。如果 WHERE 条件中涉及的列上有索引(特别是B-Tree索引),数据库可以极大地缩小搜索范围,查询速度会快几个数量级。反之,如果列上没有索引(称为“全表扫描”),数据库需要逐行检查表中的每一条记录,效率极低。

3.8 分页查询: LIMIT

当查询结果集非常大时,一次性返回所有数据是不现实的。LIMIT 子句用于限制返回的记录数量,通常用于实现分页功能。

语法:

SELECT ... FROM ... [WHERE ...] [ORDER BY ...] LIMIT [offset,] count;

  • count: 指定最多返回多少条记录。

  • offset: 可选参数,指定从第几条记录开始返回(偏移量,第一条记录的偏移量是0)。

示例1:获取前N条记录

SQL

-- 查询成绩最高的前3名学生
SELECT name, score 
FROM students 
ORDER BY score DESC 
LIMIT 3;

示例2:实现分页(例如,每页显示2条,查询第2页)

第二页的数据应该从第 (2-1) * 2 = 2 条记录(偏移量为2)开始,取2条。

SQL

-- 查询学生列表,每页2条,这是第2页的数据
SELECT id, name, score 
FROM students 
ORDER BY id ASC -- 分页查询通常需要一个确定的排序顺序,以保证每次查询的页面内容稳定
LIMIT 2, 2; -- 从偏移量为2的记录开始,取2条记录 (即第3条和第4条)

或者使用 OFFSET 关键字,更清晰:

SQL

-- 使用 OFFSET 关键字实现同样的效果
SELECT id, name, score 
FROM students 
ORDER BY id ASC
LIMIT 2 OFFSET 2;

深入扩展与注意事项:

  • LIMIT的位置LIMIT 子句必须放在 SELECT 语句的最后面。

  • 深度分页问题:当 OFFSET 值非常大时(例如 LIMIT 1000000, 10),查询性能会急剧下降。因为MySQL需要先扫描并跳过前面的100万条记录,然后才返回你需要的10条。对于需要高性能深度分页的场景,通常会采用“基于游标”或“基于键集”的分页策略,例如 WHERE id > [上一页最后一条记录的ID] ORDER BY id ASC LIMIT 10

  • SQL执行顺序:理解SELECT语句的逻辑执行顺序对写出正确的SQL至关重要:

    1. FROM:确定数据来源表。

    2. WHERE:根据条件过滤行。

    3. GROUP BY:对结果进行分组(高级主题)。

    4. HAVING:对分组后的结果进行过滤(高级主题)。

    5. SELECT:选择要显示的列或表达式。

    6. DISTINCT:对结果去重。

    7. ORDER BY:对最终结果进行排序。

    8. LIMIT:截取最终结果的指定部分。


四、 修改数据 (Update)

使用 UPDATE 语句来修改表中已存在的一条或多条记录。

语法:

UPDATE 表名 SET 列1=新值1, 列2=新值2, ... WHERE 条件;

示例:

SQL

-- 将学号为 'SN2025001' 的学生的成绩修改为 98.00,姓名修改为“张三丰”
UPDATE students 
SET 
    score = 98.00, 
    name = '张三丰' 
WHERE 
    student_no = 'SN2025001';

逐行注释与解析:

  1. UPDATE students: UPDATE 是修改数据的关键字,students 是目标表。

  2. SET score = 98.00, name = '张三丰': SET 关键字后面跟着要修改的列和它们的新值,多个“列=值”对之间用逗号隔开。

  3. WHERE student_no = 'SN2025001': WHERE 子句指定了要修改哪些行。这里是学号为 'SN2025001' 的那一行。

深入扩展与注意事项:

  • !!!极度危险:忘记WHERE子句!!!

    如果执行 UPDATE 语句时忘记写 WHERE 子句,例如:UPDATE students SET score = 60.00;,这条语句将会把表中所有行的 score 列都更新为 60.00。这是一个非常严重且常见的误操作,可能导致灾难性的数据丢失。在执行 UPDATE 操作前,务必再三检查 WHERE 条件是否正确。

  • 安全实践:在执行一个不确定的 UPDATEDELETE 语句前,可以先用相同的 WHERE 条件写一个 SELECT 语句,看看选中的是否是自己想要操作的数据。例如,先执行 SELECT * FROM students WHERE student_no = 'SN2025001';,确认查出来的是且仅是张三的数据后,再执行 UPDATE


五、 删除数据 (Delete)

使用 DELETE 语句从表中删除一条或多条记录。

语法:

DELETE FROM 表名 WHERE 条件;

示例:

SQL

-- 删除学号为 'SN2025005' 的学生记录
DELETE FROM students WHERE student_no = 'SN2025005';

逐行注释与解析:

  1. DELETE FROM students: DELETE FROM 是删除数据的关键字,students 是目标表。

  2. WHERE student_no = 'SN2025005': WHERE 子句指定了要删除哪些行。

深入扩展与注意事项:

  • !!!同样极度危险:忘记WHERE子句!!!

    如果执行 DELETE FROM students; 且没有 WHERE 子句,它将删除表中所有的行。这个操作同样是不可逆的(在没有备份或事务回滚的情况下),必须极度小心。

  • DELETE vs TRUNCATE vs DROP

    这是面试和实践中非常重要的一个区别:

    • DELETE FROM students;:

      • 属于 DML (数据操作语言)。

      • 逐行删除,并且每删除一行都会记录日志。

      • 如果在一个事务中执行,可以被回滚 (ROLLBACK)

      • 删除时会触发为该表定义的触发器 (Trigger)

      • 不会重置 AUTO_INCREMENT 的值。如果删除了所有数据,新插入的数据ID会接着之前的最大ID继续增长。

      • 对于大表来说,速度很慢。

    • TRUNCATE TABLE students;:

      • 属于 DDL (数据定义语言)。

      • 它不是逐行删除,而是通过释放存储表数据的数据页来一次性清空表,速度极快。

      • 通常不能被回滚(在某些数据库系统中可能可以,但行为不统一)。

      • 不会触发删除触发器。

      • 重置 AUTO_INCREMENT 的值回到初始状态(通常是1)。

    • DROP TABLE students;:

      • 属于 DDL (数据定义语言)。

      • 彻底删除整个表,包括表的结构定义和所有数据。

      • 执行后,students 这张表将不复存在。


六、 内容重点总结

至此,我们已经详细学习了 MySQL 最基础的增、删、改、查操作。我们来回顾一下核心要点:

  • 新增 (Create): 使用 INSERT INTO。推荐使用指定列插入的方式,并可一次性插入多行以提高效率。

    • INSERT INTO table (col1, col2) VALUES (val1, val2);

  • 查询 (Retrieve): 使用 SELECT,功能最丰富。

    • 避免使用 SELECT *,明确指定所需列。

    • 可以使用表达式进行计算,用别名 (AS) 提高可读性。

    • DISTINCT 用于结果去重。

    • ORDER BY 用于结果排序 (ASC/DESC)。

    • WHERE 是查询的灵魂,通过各种条件(比较、范围、列表、模糊、逻辑)过滤数据。

    • LIMIT 用于分页,限制返回的行数。

  • 修改 (Update): 使用 UPDATE ... SET ...核心是WHERE子句,绝对不能省略,否则将更新整张表。

    • UPDATE table SET col1=val1 WHERE condition;

  • 删除 (Delete): 使用 DELETE FROM ...核心也是WHERE子句,绝对不能省略,否则将删除整张表。

    • DELETE FROM table WHERE condition;

  • 安全第一: 对于 UPDATEDELETE 操作,永远要先用 SELECT 搭配相同的 WHERE 条件来验证你将要影响的数据行是否正确。

七、 课后作业 (实践练习建议)

学习数据库最好的方式就是不断练习。基于我们创建的 students 表,你可以尝试完成以下任务来巩固所学知识:

  1. 新增:

    • 再插入3名新的学生信息,其中一名学生的 score 留空(即 NULL)。

    • 尝试使用 INSERT IGNORE 插入一条与现有 student_no 冲突的记录,并观察结果。

  2. 查询:

    • 查询所有成绩在80分到90分之间的女同学的姓名和学号。

    • 查询所有在2025年9月1日入学的,且不姓“张”的学生信息。

    • 查询所有学生信息,按年龄降序排列,如果年龄相同,则按入学日期升序排列。

    • 查询成绩为空(NULL)的学生。

    • 查询出所有学生姓名的第一个字(提示:可以使用字符串函数 SUBSTRING())。

    • 查询学生列表,每页显示3条,请写出查询第3页数据的SQL语句。

  3. 修改:

    • 将所有年龄为空的学生,年龄更新为18岁。

    • 将总分排名第一的学生的成绩加1分(提示:需要结合 ORDER BYLIMIT)。

  4. 删除:

    • 删除所有年龄大于20岁的学生记录。

通过完成这些练习,你将能更深刻地理解和记忆这些基础但至关重要的SQL操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值