Appearance
数据操作
本章将介绍MySQL中数据的插入、更新和删除操作,即CRUD操作中的C(Create)、U(Update)、D(Delete)。
插入数据
基本插入
sql
-- 创建示例表
CREATE TABLE students (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
age INT,
gender ENUM('男', '女'),
score DECIMAL(5, 2)
);
-- 插入单条数据(指定列名)
INSERT INTO students (name, age, gender, score)
VALUES ('张三', 20, '男', 95.5);
-- 插入单条数据(不指定列名,需按顺序)
INSERT INTO students
VALUES (NULL, '李四', 21, '女', 88.0);
-- NULL表示让AUTO_INCREMENT自动生成ID
-- 查看插入的数据
SELECT * FROM students;批量插入
sql
-- 批量插入多条数据
INSERT INTO students (name, age, gender, score) VALUES
('王五', 22, '男', 92.0),
('赵六', 19, '女', 85.5),
('钱七', 23, '男', 90.0);
-- 查看所有数据
SELECT * FROM students;
/*
* 批量插入的优点:
* 1. 减少网络传输次数
* 2. 提高插入效率
* 3. 减少事务开销
*/插入查询结果
sql
-- 创建备份表
CREATE TABLE students_backup LIKE students;
-- 将查询结果插入到另一个表
INSERT INTO students_backup (name, age, gender, score)
SELECT name, age, gender, score FROM students WHERE score >= 90;
-- 查看备份表
SELECT * FROM students_backup;插入特殊值
sql
-- 插入NULL值
INSERT INTO students (name, age, gender, score)
VALUES ('孙八', NULL, '男', NULL);
-- 插入默认值
INSERT INTO students (name, age, gender, score)
VALUES ('周九', DEFAULT, '女', DEFAULT);
-- 使用DEFAULT关键字
INSERT INTO students
VALUES (DEFAULT, '吴十', DEFAULT, DEFAULT, DEFAULT);
-- 使用表达式
INSERT INTO students (name, age, gender, score)
VALUES ('测试用户', 18 + 2, '男', 80 + 10);INSERT IGNORE
sql
-- 创建带唯一约束的表
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) UNIQUE,
email VARCHAR(100) UNIQUE
);
INSERT INTO users (username, email) VALUES ('user1', 'user1@test.com');
-- 普通插入会报错(重复键)
-- INSERT INTO users (username, email) VALUES ('user1', 'user2@test.com');
-- Error: Duplicate entry 'user1' for key 'username'
-- 使用INSERT IGNORE忽略错误
INSERT IGNORE INTO users (username, email)
VALUES ('user1', 'user2@test.com');
-- 不会报错,但也不会插入数据
-- 查看受影响的行数
SELECT ROW_COUNT(); -- 返回0表示没有插入INSERT ... ON DUPLICATE KEY UPDATE
sql
-- 如果记录存在则更新,不存在则插入
INSERT INTO users (username, email)
VALUES ('user1', 'newemail@test.com')
ON DUPLICATE KEY UPDATE email = VALUES(email);
-- 或使用更清晰的写法
INSERT INTO users (username, email)
VALUES ('user1', 'updated@test.com')
ON DUPLICATE KEY UPDATE
email = VALUES(email),
username = VALUES(username);
-- 查看结果
SELECT * FROM users;REPLACE
sql
-- REPLACE:先删除再插入
-- 如果存在则删除旧记录,插入新记录
REPLACE INTO users (id, username, email)
VALUES (1, 'user1_updated', 'user1_updated@test.com');
-- 注意:REPLACE会删除旧记录,可能导致自增ID变化
SELECT * FROM users;更新数据
基本更新
sql
-- 更新单个字段
UPDATE students
SET score = 96.0
WHERE name = '张三';
-- 更新多个字段
UPDATE students
SET age = 21, score = 97.0
WHERE name = '张三';
-- 查看更新结果
SELECT * FROM students WHERE name = '张三';条件更新
sql
-- 更新多条记录
UPDATE students
SET score = score + 5
WHERE gender = '女';
-- 使用表达式更新
UPDATE students
SET score = score * 1.1
WHERE score < 90;
-- 使用CASE表达式
UPDATE students
SET score = CASE
WHEN score >= 90 THEN 100
WHEN score >= 80 THEN score + 5
ELSE score + 10
END;
-- 使用子查询更新
UPDATE students
SET score = (
SELECT AVG(score) FROM students
)
WHERE score IS NULL;多表更新
sql
-- 创建关联表
CREATE TABLE departments (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50)
);
CREATE TABLE employees (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
salary DECIMAL(10, 2),
department_id INT
);
INSERT INTO departments (name) VALUES ('技术部'), ('销售部');
INSERT INTO employees (name, salary, department_id)
VALUES ('张三', 10000, 1), ('李四', 8000, 2);
-- 多表更新
UPDATE employees e
JOIN departments d ON e.department_id = d.id
SET e.salary = e.salary * 1.1
WHERE d.name = '技术部';
SELECT * FROM employees;安全更新
sql
/*
* 更新操作注意事项:
*
* 1. 始终使用WHERE子句
* 2. 更新前先用SELECT验证
* 3. 使用事务确保安全
* 4. 备份重要数据
*/
-- 错误示例:更新所有记录
-- UPDATE students SET score = 0; -- 危险!
-- 正确做法:先查询再更新
SELECT * FROM students WHERE id = 1;
UPDATE students SET score = 0 WHERE id = 1;
-- 使用事务
START TRANSACTION;
UPDATE students SET score = 100 WHERE id = 1;
-- 检查结果
SELECT * FROM students WHERE id = 1;
-- 确认无误后提交
COMMIT;
-- 或回滚
-- ROLLBACK;删除数据
基本删除
sql
-- 删除单条记录
DELETE FROM students WHERE id = 10;
-- 删除多条记录
DELETE FROM students WHERE score < 60;
-- 删除所有记录(危险!)
-- DELETE FROM students; -- 不推荐
-- 查看删除后的数据
SELECT * FROM students;条件删除
sql
-- 使用复杂条件删除
DELETE FROM students
WHERE age > 25 AND gender = '男';
-- 使用子查询删除
DELETE FROM students
WHERE id IN (
SELECT id FROM students_backup
);
-- 使用LIMIT限制删除数量
DELETE FROM students
WHERE score < 70
LIMIT 10; -- 最多删除10条
-- 按顺序删除
DELETE FROM students
ORDER BY score ASC
LIMIT 5; -- 删除分数最低的5条多表删除
sql
-- 创建关联数据
CREATE TABLE orders (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
amount DECIMAL(10, 2)
);
CREATE TABLE order_items (
id INT PRIMARY KEY AUTO_INCREMENT,
order_id INT,
product_name VARCHAR(100)
);
INSERT INTO orders (user_id, amount) VALUES (1, 100), (2, 200);
INSERT INTO order_items (order_id, product_name) VALUES (1, '商品A'), (1, '商品B');
-- 多表删除
DELETE o, oi
FROM orders o
JOIN order_items oi ON o.id = oi.order_id
WHERE o.user_id = 1;
-- 使用LEFT JOIN删除
DELETE o
FROM orders o
LEFT JOIN order_items oi ON o.id = oi.order_id
WHERE oi.id IS NULL; -- 删除没有订单项的订单TRUNCATE vs DELETE
sql
/*
* TRUNCATE vs DELETE:
*
* DELETE:
* - 可以带WHERE条件
* - 逐行删除,记录日志
* - 不会重置AUTO_INCREMENT
* - 可以回滚(在事务中)
* - 触发器会被触发
*
* TRUNCATE:
* - 删除所有数据
* - 整表删除,不记录日志
* - 重置AUTO_INCREMENT
* - 不能回滚
* - 触发器不会被触发
* - 执行更快
*/
-- 使用DELETE
DELETE FROM students;
-- 使用TRUNCATE
TRUNCATE TABLE students;
-- TRUNCATE后自增ID重置
INSERT INTO students (name, age, gender, score)
VALUES ('新学生', 20, '男', 90);
SELECT * FROM students; -- id从1开始实际应用示例
sql
-- 创建完整的示例数据库
CREATE DATABASE IF NOT EXISTS shop;
USE shop;
-- 用户表
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(100) NOT NULL,
email VARCHAR(100),
phone VARCHAR(20),
status TINYINT DEFAULT 1 COMMENT '1正常 0禁用',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 商品表
CREATE TABLE products (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
stock INT DEFAULT 0,
category_id INT,
status TINYINT DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 订单表
CREATE TABLE orders (
id INT PRIMARY KEY AUTO_INCREMENT,
order_no VARCHAR(32) NOT NULL UNIQUE,
user_id INT NOT NULL,
total_amount DECIMAL(10, 2) DEFAULT 0,
status TINYINT DEFAULT 0 COMMENT '0待支付 1已支付 2已发货 3已完成 4已取消',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 订单明细表
CREATE TABLE order_items (
id INT PRIMARY KEY AUTO_INCREMENT,
order_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT NOT NULL DEFAULT 1,
price DECIMAL(10, 2) NOT NULL
);
-- 插入测试数据
INSERT INTO users (username, password, email, phone) VALUES
('user1', 'password123', 'user1@test.com', '13800000001'),
('user2', 'password123', 'user2@test.com', '13800000002'),
('user3', 'password123', 'user3@test.com', '13800000003');
INSERT INTO products (name, price, stock) VALUES
('iPhone 15', 7999.00, 100),
('MacBook Pro', 14999.00, 50),
('AirPods', 1299.00, 200);
-- 创建订单
INSERT INTO orders (order_no, user_id, total_amount) VALUES
('ORD001', 1, 9298.00),
('ORD002', 2, 14999.00);
-- 添加订单明细
INSERT INTO order_items (order_id, product_id, quantity, price) VALUES
(1, 1, 1, 7999.00),
(1, 3, 1, 1299.00),
(2, 2, 1, 14999.00);
-- 更新订单状态
UPDATE orders SET status = 1 WHERE order_no = 'ORD001';
-- 更新库存
UPDATE products SET stock = stock - 1 WHERE id = 1;
-- 查询订单详情
SELECT
o.order_no,
u.username,
p.name AS product_name,
oi.quantity,
oi.price
FROM orders o
JOIN users u ON o.user_id = u.id
JOIN order_items oi ON o.id = oi.order_id
JOIN products p ON oi.product_id = p.id;本章小结
本章学习了:
- 插入数据:INSERT、INSERT IGNORE、REPLACE
- 批量插入:多值插入、INSERT...SELECT
- 更新数据:UPDATE、多表更新、条件更新
- 删除数据:DELETE、TRUNCATE、多表删除
- 安全操作:使用事务、先查询再操作
下一章,我们将学习查询进阶,了解更复杂的查询技巧。
