Skip to content

MySql

三范式

一范式:字段原子不可分 二范式:完全依赖主键身
三范式:直接依赖不传递 设计时:先范式后性能

第一范式 原子性

每个字段都是不可再分的最小数据单元

第二范式 主键依赖

表中所有非主键字段都必须完全依赖于整个主键

第三范式 传递依赖

表中所有非主键字段之间不能有传递依赖

执行顺序

  1. FROM + JOIN
  2. WHERE
  3. GROUP BY
  4. HAVING
  5. SELECT
  6. DISTINCT
  7. ORDER BY
  8. LIMIT/OFFSET

insert

单条

-- 基本语法
INSERT INTO table_name (column1, column2, column3) 
VALUES (value1, value2, value3);

-- 学生表示例
INSERT INTO students (name, age, gender, class_id) 
VALUES ('张三', 18, '男', 1);

-- 如果插入所有列,可以省略列名
INSERT INTO students 
VALUES (NULL, '李四', 19, '女', 2, '2024-01-15');

批量

-- 方法一:多组VALUES(推荐)
INSERT INTO students (name, age, gender, class_id) 
VALUES 
    ('王五', 17, '男', 1),
    ('赵六', 18, '女', 2),
    ('钱七', 19, '男', 1),
    ('孙八', 17, '女', 3);

-- 方法二:INSERT SELECT(从其他表插入)
INSERT INTO student_archive (name, age, gender)
SELECT name, age, gender 
FROM students 
WHERE graduate_year = 2023;

-- 方法三:创建临时表批量插入
CREATE TEMPORARY TABLE temp_students (
    name VARCHAR(50),
    age INT,
    gender VARCHAR(10)
);

INSERT INTO temp_students VALUES 
('周九', 18, '男'),
('吴十', 19, '女');

INSERT INTO students (name, age, gender)
SELECT name, age, gender FROM temp_students;

update

单条

-- 基本语法
UPDATE table_name 
SET column1 = value1, column2 = value2 
WHERE condition;

-- 更新单个学生年龄
UPDATE students 
SET age = 19 
WHERE id = 1;

-- 更新多个字段
UPDATE students 
SET age = 20, class_id = 3, update_time = NOW() 
WHERE name = '张三';

-- 基于原值更新
UPDATE products 
SET price = price * 1.1,  -- 涨价10%
    stock = stock - 1     -- 库存减1
WHERE id = 100;

批量

-- 批量更新同一条件的数据
UPDATE students 
SET status = '毕业' 
WHERE graduate_year = 2024;

-- 使用CASE条件批量更新
UPDATE students 
SET score_level = 
    CASE 
        WHEN score >= 90 THEN 'A'
        WHEN score >= 80 THEN 'B' 
        WHEN score >= 70 THEN 'C'
        WHEN score >= 60 THEN 'D'
        ELSE 'E'
    END;

-- 联表更新(基于其他表更新)
UPDATE students s
JOIN classes c ON s.class_id = c.id
SET s.class_name = c.name,
    s.update_time = NOW()
WHERE c.grade = '三年级';

-- 批量更新前N条记录
UPDATE students 
SET status = '优秀' 
WHERE id IN (
    SELECT id FROM students 
    ORDER BY score DESC 
    LIMIT 10
);

delete

单条

-- 基本语法
DELETE FROM table_name WHERE condition;

-- 删除特定学生
DELETE FROM students WHERE id = 5;

-- 删除特定条件的数据
DELETE FROM students WHERE name = '张三' AND class_id = 1;

批量

-- 批量删除符合条件的数据
DELETE FROM students WHERE graduate_year < 2020;

-- 删除重复数据(保留一条)
DELETE FROM students 
WHERE id NOT IN (
    SELECT MIN(id) 
    FROM students 
    GROUP BY name, id_card
);

-- 联表删除
DELETE s
FROM students s
JOIN classes c ON s.class_id = c.id
WHERE c.status = '停用';

-- 清空表数据(谨慎使用!)
DELETE FROM students;  -- 可回滚
TRUNCATE TABLE students;  -- 不可回滚,更快

表格合并(union)

特性

  • UNION:会去重,性能较慢

  • UNION ALL不去重,性能更快

  • 能不用 UNION 就不用 UNION,能用 UNION ALL 就用 UNION ALL

UNIONUNION ALL
重复数据处理自动去除重复行保留所有行,包括重复的
性能较慢(需要排序去重)较快(直接合并)
排序通常会对结果排序不保证顺序
使用场景需要去重时不需要去重或确定无重复时
资源消耗较高(需要临时表去重)较低

注意事项

1.字段必须匹配

sql
-- ✅ 正确:列数相同,数据类型兼容
SELECT id, name, created_date FROM table1
UNION ALL
SELECT user_id, username, register_date FROM table2;

-- ❌ 错误:列数不同
SELECT id, name FROM table1
UNION ALL
SELECT id FROM table2;  -- 错误:列数不匹配

-- ❌ 错误:数据类型不匹配
SELECT id, name FROM table1  -- id是数字,name是字符串
UNION ALL
SELECT name, id FROM table2;  -- 第一列是字符串,第二列是数字

2.ORDER BY 使用规则

sql
-- ✅ 正确:ORDER BY 必须在最后
SELECT name, score FROM class_a
UNION ALL
SELECT name, score FROM class_b
ORDER BY score DESC;  -- 对整个结果排序

-- ✅ 正确:单个查询排序要用括号
(SELECT name, score FROM class_a ORDER BY score DESC)
UNION ALL
(SELECT name, score FROM class_b ORDER BY name ASC);

-- ❌ 错误:ORDER BY 不能在中间
SELECT name FROM table1 ORDER BY name
UNION ALL  -- 错误!
SELECT name FROM table2;

3.列名和别名

sql
-- 最终结果使用第一个SELECT的列名
SELECT id AS user_id, name FROM employees
UNION ALL
SELECT emp_no, emp_name FROM contractors;
-- 结果列名:user_id, name(来自第一个SELECT)

© 2025-甘草味道的博客