【MySQL】数据表删除数据

在这里插入图片描述

个人主页:Guiat
归属专栏:MySQL

在这里插入图片描述

正文

1. 数据删除基础概念

1.1 删除操作的重要性

数据删除的重要性
数据生命周期管理
存储空间优化
性能维护
合规性要求
数据清理
历史数据归档
过期数据删除
减少存储成本
优化索引大小
查询性能提升
维护表分析效率
GDPR合规
数据留存策略
清理测试数据
移除重复记录

1.2 删除操作风险分析

删除操作风险
数据丢失风险
级联删除影响
性能影响
锁定问题
无备份的永久丢失
错误条件导致过量删除
引用完整性破坏
意外触发级联删除
大批量删除造成系统负载
锁表影响其他操作
行锁/表锁阻塞其他事务
死锁风险

2. DELETE语句详解

2.1 DELETE基本语法结构

DELETE语句结构
DELETE FROM 子句
WHERE 子句
ORDER BY 子句
LIMIT 子句
指定要删除记录的表
指定删除条件
省略则删除所有行
指定删除顺序
限制删除的行数

2.2 基本DELETE示例

-- 删除单条记录
DELETE FROM customers
WHERE customer_id = 1001;

-- 删除多条符合条件的记录
DELETE FROM products
WHERE category = 'discontinued' AND stock = 0;

-- 删除日期范围内的记录
DELETE FROM orders
WHERE order_date < '2022-01-01';

2.3 使用ORDER BY和LIMIT控制删除

ORDER BY和LIMIT删除控制
删除指定数量记录
控制删除的优先级
分批删除大量数据
DELETE FROM logs LIMIT 1000
DELETE FROM tasks
ORDER BY priority, created_at
LIMIT 500
控制系统负载
减少锁定时间
-- 删除最旧的1000条日志
DELETE FROM system_logs
ORDER BY created_at ASC
LIMIT 1000;

-- 先删除优先级低的任务
DELETE FROM tasks
WHERE status = 'completed'
ORDER BY priority ASC, completion_date ASC
LIMIT 500;

3. 高级DELETE操作

3.1 多表删除

多表删除
使用JOIN关联多表
基于关系删除数据
维护数据一致性
DELETE t1 FROM table1 t1
JOIN table2 t2 ON t1.id = t2.id
WHERE condition
根据一个表的条件
删除另一个表的记录
解决孤立记录问题
-- 删除所有已取消订单的订单项
DELETE oi
FROM order_items oi
JOIN orders o ON oi.order_id = o.order_id
WHERE o.status = 'cancelled';

-- 删除没有对应用户的所有评论
DELETE c
FROM comments c
LEFT JOIN users u ON c.user_id = u.user_id
WHERE u.user_id IS NULL;

3.2 使用子查询的DELETE

子查询DELETE
WHERE子句中使用子查询
复杂条件匹配
基于聚合结果删除
DELETE FROM products
WHERE category_id IN (
SELECT id FROM categories
WHERE discontinued = TRUE
)
多级关联条件
基于统计或计算结果
-- 删除所有已停产类别的产品
DELETE FROM products
WHERE category_id IN (
    SELECT id FROM categories WHERE discontinued = TRUE
);

-- 删除没有订单的客户
DELETE FROM customers
WHERE customer_id NOT IN (
    SELECT DISTINCT customer_id FROM orders
);

-- 删除低于平均销量的产品
DELETE FROM products
WHERE sales_count < (
    SELECT AVG(sales_count) FROM products
);

3.3 使用事务进行安全删除

事务安全删除
BEGIN/START TRANSACTION
执行DELETE操作
验证影响行数
COMMIT或ROLLBACK
开始事务
执行预期的删除
检查ROW_COUNT()
验证是否符合预期
符合预期则COMMIT
不符合预期则ROLLBACK
-- 使用事务安全删除
START TRANSACTION;

-- 删除操作
DELETE FROM important_data
WHERE last_updated < '2022-01-01';

-- 检查影响的行数
SELECT ROW_COUNT() AS deleted_rows;

-- 如果删除的行数符合预期,提交事务
-- COMMIT;

-- 如果删除的行数不符合预期,回滚事务
-- ROLLBACK;

4. TRUNCATE TABLE操作

4.1 TRUNCATE与DELETE的区别

TRUNCATE vs DELETE
执行速度
事务支持
自增ID处理
触发器行为
条件过滤
TRUNCATE: 非常快
DELETE: 相对较慢
TRUNCATE: 隐式提交,不可回滚
DELETE: 完全支持事务
TRUNCATE: 重置为初始值
DELETE: 不重置
TRUNCATE: 不触发DELETE触发器
DELETE: 触发DELETE触发器
TRUNCATE: 不支持WHERE条件
DELETE: 支持WHERE条件

4.2 TRUNCATE使用场景

TRUNCATE适用场景
完全清空表
重置自增ID
测试数据重置
临时表清理
大批量数据导入前清理
需要删除表中所有数据
希望自增ID重新从1开始
测试环境数据初始化
会话结束前清空临时表
ETL过程中的中间表重置
-- 完全清空临时表
TRUNCATE TABLE temp_import_data;

-- 重置测试数据
TRUNCATE TABLE test_customers;
TRUNCATE TABLE test_orders;

5. 批量删除策略

5.1 分批删除大量数据

分批删除策略
确定批次大小
循环删除批次
监控系统资源
允许间隔休息
通常500-10000行/批
DELETE...LIMIT循环
存储过程自动化
监控锁等待和CPU利用率
批次之间添加短暂延迟
减少对系统的影响
-- 分批删除存储过程示例
DELIMITER //
CREATE PROCEDURE batch_delete_old_logs()
BEGIN
    DECLARE done INT DEFAULT FALSE;
    DECLARE deleted_count INT DEFAULT 0;
    DECLARE batch_size INT DEFAULT 5000;
    DECLARE total_deleted INT DEFAULT 0;
    
    -- 开始循环删除
    batch_loop: LOOP
        -- 删除一批数据
        DELETE FROM system_logs 
        WHERE log_date < DATE_SUB(CURRENT_DATE, INTERVAL 1 YEAR)
        LIMIT batch_size;
        
        -- 获取影响的行数
        SET deleted_count = ROW_COUNT();
        SET total_deleted = total_deleted + deleted_count;
        
        -- 如果没有更多数据可删除,退出循环
        IF deleted_count = 0 THEN
            LEAVE batch_loop;
        END IF;
        
        -- 增加短暂延迟让系统"呼吸"
        DO SLEEP(0.5);
    END LOOP;
    
    -- 返回删除的总行数
    SELECT CONCAT('Total deleted: ', total_deleted, ' rows') AS result;
END //
DELIMITER ;

-- 执行存储过程
CALL batch_delete_old_logs();

5.2 使用临时表辅助删除

临时表辅助删除
创建临时表存储ID
填充要删除的ID
基于临时表删除数据
处理大表关联删除
CREATE TEMPORARY TABLE
temp_delete_ids (id INT PRIMARY KEY)
INSERT INTO temp_delete_ids
SELECT id FROM main_table
WHERE complex_condition
DELETE FROM main_table
WHERE id IN (
SELECT id FROM temp_delete_ids
)
或使用JOIN方式删除
避免复杂条件反复评估
提高删除性能
-- 创建临时表存储要删除的ID
CREATE TEMPORARY TABLE temp_orders_to_delete (
    order_id INT PRIMARY KEY
);

-- 填充临时表
INSERT INTO temp_orders_to_delete
SELECT order_id
FROM orders
WHERE order_date < '2022-01-01'
AND status = 'completed'
AND (SELECT SUM(amount) FROM order_items WHERE order_items.order_id = orders.order_id) < 10;

-- 先删除关联表中的数据
DELETE oi FROM order_items oi
JOIN temp_orders_to_delete t ON oi.order_id = t.order_id;

-- 再删除主表中的数据
DELETE o FROM orders o
JOIN temp_orders_to_delete t ON o.order_id = t.order_id;

-- 清理临时表
DROP TEMPORARY TABLE temp_orders_to_delete;

6. 特殊删除场景

6.1 级联删除

级联删除
外键级联删除设置
手动实现级联删除
触发器实现级联删除
ON DELETE CASCADE
自动删除关联记录
手动删除子表记录
再删除主表记录
通过触发器控制复杂级联逻辑
-- 创建带级联删除的外键
ALTER TABLE order_items
ADD CONSTRAINT fk_order_items_orders
FOREIGN KEY (order_id) REFERENCES orders(order_id)
ON DELETE CASCADE;

-- 手动实现级联删除
START TRANSACTION;

-- 先删除子表记录
DELETE FROM order_items WHERE order_id = 1001;
DELETE FROM order_shipments WHERE order_id = 1001;
DELETE FROM order_payments WHERE order_id = 1001;

-- 再删除主表记录
DELETE FROM orders WHERE order_id = 1001;

COMMIT;

6.2 软删除策略

软删除策略
不物理删除数据
使用状态标记
记录删除时间
虚拟删除的优势
保留数据历史
使用is_deleted标志
使用status='deleted'
记录deleted_at时间戳
支持数据恢复
审计跟踪支持
避免物理删除开销
-- 添加软删除相关字段
ALTER TABLE customers
ADD is_deleted TINYINT(1) DEFAULT 0,
ADD deleted_at DATETIME DEFAULT NULL;

-- 执行软删除
UPDATE customers
SET is_deleted = 1,
    deleted_at = NOW()
WHERE customer_id = 1001;

-- 查询时排除软删除的记录
SELECT * FROM customers
WHERE is_deleted = 0;

-- 创建视图简化查询
CREATE VIEW active_customers AS
SELECT * FROM customers
WHERE is_deleted = 0;

6.3 分区表删除策略

分区表删除策略
DROP PARTITION
ALTER TABLE...TRUNCATE PARTITION
分区轮换技术
完全移除分区及其数据
清空分区但保留分区结构
EXCHANGE PARTITION
实现快速数据替换
-- 创建按月分区的表
CREATE TABLE log_events (
    id INT NOT NULL,
    log_date DATE NOT NULL,
    message VARCHAR(255),
    PRIMARY KEY (id, log_date)
)
PARTITION BY RANGE (YEAR(log_date) * 100 + MONTH(log_date)) (
    PARTITION p202201 VALUES LESS THAN (202202),
    PARTITION p202202 VALUES LESS THAN (202203),
    PARTITION p202203 VALUES LESS THAN (202204),
    PARTITION pfuture VALUES LESS THAN MAXVALUE
);

-- 清空指定分区
ALTER TABLE log_events TRUNCATE PARTITION p202201;

-- 删除指定分区
ALTER TABLE log_events DROP PARTITION p202201;

-- 添加新分区
ALTER TABLE log_events ADD PARTITION (
    PARTITION p202204 VALUES LESS THAN (202205)
);

7. 删除数据安全策略

7.1 备份与回滚策略

删除前备份策略
完整备份
表级备份
导出要删除的数据
建立测试环境验证
使用mysqldump备份整个库
使用CREATE TABLE AS SELECT
使用mysqldump --tables
将要删除的数据导出保存
在测试库先执行删除操作
验证结果
-- 在删除前创建表的备份
CREATE TABLE customers_backup AS
SELECT * FROM customers;

-- 备份要删除的数据
CREATE TABLE deleted_customers_archive AS
SELECT * FROM customers
WHERE last_activity_date < '2020-01-01';

-- 执行删除前验证将被删除的记录数
SELECT COUNT(*) AS to_be_deleted
FROM customers
WHERE last_activity_date < '2020-01-01';

-- 执行删除,带有事务保护
START TRANSACTION;

DELETE FROM customers
WHERE last_activity_date < '2020-01-01';

-- 验证结果
SELECT COUNT(*) AS remaining FROM customers;

-- 确认无误后提交,有误则回滚
-- COMMIT;
-- 或
-- ROLLBACK;

7.2 日志和审计

删除操作审计
启用MySQL审计日志
创建删除操作触发器
记录应用级删除审计
使用审计插件
配置binlog记录所有删除
BEFORE DELETE触发器
记录被删除的数据
应用层记录谁执行了删除
记录删除条件和时间
-- 创建审计表
CREATE TABLE delete_audit_log (
    audit_id INT AUTO_INCREMENT PRIMARY KEY,
    table_name VARCHAR(64) NOT NULL,
    record_id VARCHAR(100) NOT NULL,
    deleted_by VARCHAR(100) NOT NULL,
    deleted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    record_data JSON
);

-- 创建触发器记录删除操作
DELIMITER //
CREATE TRIGGER customers_before_delete
BEFORE DELETE ON customers
FOR EACH ROW
BEGIN
    INSERT INTO delete_audit_log (
        table_name,
        record_id,
        deleted_by,
        record_data
    )
    VALUES (
        'customers',
        OLD.customer_id,
        CURRENT_USER(),
        JSON_OBJECT(
            'customer_id', OLD.customer_id,
            'name', OLD.name,
            'email', OLD.email,
            'created_at', OLD.created_at,
            'last_activity_date', OLD.last_activity_date
        )
    );
END //
DELIMITER ;

8. 实际应用场景

8.1 数据归档和清理

数据归档与清理
定义数据保留策略
数据归档过程
定期清理流程
依据业务需求确定保留期限
区分热数据和冷数据
归档到历史表
归档到单独的数据库
导出到外部存储
定期自动化清理
监控清理结果
-- 数据归档示例: 归档旧订单到历史表
-- 1. 创建归档表
CREATE TABLE orders_archive LIKE orders;

-- 2. 归档数据
INSERT INTO orders_archive
SELECT * FROM orders
WHERE order_date < DATE_SUB(CURRENT_DATE, INTERVAL 2 YEAR);

-- 3. 验证归档
SELECT COUNT(*) FROM orders_archive;

-- 4. 删除已归档数据
DELETE FROM orders
WHERE order_date < DATE_SUB(CURRENT_DATE, INTERVAL 2 YEAR);

-- 自动化归档和清理存储过程
DELIMITER //
CREATE PROCEDURE archive_old_data(archive_date DATE)
BEGIN
    DECLARE archived_count INT DEFAULT 0;
    
    START TRANSACTION;
    
    -- 归档旧数据
    INSERT INTO orders_archive
    SELECT * FROM orders
    WHERE order_date < archive_date;
    
    SET archived_count = ROW_COUNT();
    
    -- 删除已归档数据
    DELETE FROM orders 
    WHERE order_date < archive_date;
    
    COMMIT;
    
    -- 返回处理结果
    SELECT CONCAT('Archived and deleted ', archived_count, ' records') AS result;
END //
DELIMITER ;

8.2 数据清洗和去重

数据清洗和去重
识别重复数据
保留最佳记录
删除重复记录
使用GROUP BY识别重复
使用窗口函数识别重复
决定保留规则
最新的/最完整的/手动标记
使用自连接删除重复
使用ROW_NUMBER删除重复
-- 识别重复记录
SELECT email, COUNT(*) AS count
FROM customers
GROUP BY email
HAVING COUNT(*) > 1;

-- 使用窗口函数标记重复(MySQL 8.0+)
WITH duplicates AS (
    SELECT 
        customer_id,
        email,
        ROW_NUMBER() OVER (PARTITION BY email ORDER BY created_at DESC) AS row_num
    FROM customers
)
SELECT * FROM duplicates WHERE row_num > 1;

-- 删除重复记录,保留最新的
DELETE c1 FROM customers c1
JOIN customers c2 ON c1.email = c2.email
WHERE c1.customer_id < c2.customer_id;

-- 使用临时表方法删除重复
CREATE TEMPORARY TABLE unique_customers AS
SELECT MAX(customer_id) AS customer_id
FROM customers
GROUP BY email;

DELETE FROM customers
WHERE customer_id NOT IN (
    SELECT customer_id FROM unique_customers
);

DROP TEMPORARY TABLE unique_customers;

8.3 GDPR与数据隐私合规

GDPR数据删除
用户请求删除流程
数据匿名化
删除与保留平衡
确认用户身份
识别所有关联数据
执行完整删除
替代物理删除
移除识别信息
保留统计价值
合规删除但满足业务需求
透明删除政策
-- GDPR用户数据删除示例

-- 1. 创建用户删除请求记录
INSERT INTO deletion_requests (user_id, request_date, status)
VALUES (1001, NOW(), 'pending');

-- 2. 开始删除流程
START TRANSACTION;

-- 3. 删除用户相关所有数据
-- 删除用户评论
DELETE FROM comments WHERE user_id = 1001;

-- 删除用户订单项
DELETE oi FROM order_items oi
JOIN orders o ON oi.order_id = o.order_id
WHERE o.user_id = 1001;

-- 删除用户订单
DELETE FROM orders WHERE user_id = 1001;

-- 删除用户收货地址
DELETE FROM shipping_addresses WHERE user_id = 1001;

-- 删除用户支付方式(或匿名化)
UPDATE payment_methods
SET card_number = 'XXXXXXXXXXXX1234',
    cardholder_name = 'ANONYMIZED',
    expiry_date = NULL,
    anonymized = TRUE
WHERE user_id = 1001;

-- 最后删除用户账户
DELETE FROM users WHERE user_id = 1001;

-- 4. 更新删除请求状态
UPDATE deletion_requests
SET status = 'completed', completed_at = NOW()
WHERE user_id = 1001;

COMMIT;

结语
感谢您的阅读!期待您的一键三连!欢迎指正!

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Guiat

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值