truncate - >这会重置整个表,有没有办法通过truncate来重置特定的记录/检查条件。
例如:我想重置所有数据并在表格中保留最近30天。
感谢。
答案 0 :(得分:53)
不,TRUNCATE
全有或全无。您可以执行DELETE FROM <table> WHERE <conditions>
,但这会失去TRUNCATE
的速度优势。
答案 1 :(得分:27)
简短的回答是 否 :MySQL 不允许您向WHERE
添加TRUNCATE
子句声明。这是关于TRUNCATE
声明的MySQL's documentation。
但好消息是你可以(有点)解决这个限制。
使用DELETE
首先,如果表格足够小,只需使用DELETE
语句(必须提及):
1. LOCK TABLE my_table WRITE;
2. DELETE FROM my_table WHERE my_date<DATE_SUB(NOW(), INTERVAL 1 MONTH);
3. UNLOCK TABLES;
LOCK
和UNLOCK
语句不是强制性的,但它们会加快速度并避免潜在的死锁。
不幸的是,如果您的表很大,这将非常慢......并且由于您正在考虑使用TRUNCATE
语句,我认为这是因为您的表很大。
所以这是使用TRUNCATE
语句解决问题的一种方法:
使用TRUNCATE
1. CREATE TABLE my_table_backup AS
SELECT * FROM my_table WHERE my_date>=DATE_SUB(NOW(), INTERVAL 1 MONTH);
2. TRUNCATE my_table;
3. LOCK TABLE my_table WRITE, my_table_backup WRITE;
4. INSERT INTO my_table SELECT * FROM my_table_backup;
5. UNLOCK TABLES;
6. DROP TABLE my_table_backup;
不幸的是,如果其他进程同时在表中插入记录,这个解决方案有点不安全:
TRUNCATE
语句将AUTO-INCREMENT
计数器重置为零。因此,在步骤2和3之间插入的任何记录都将具有一个低于旧ID的ID,甚至可能与在步骤4中插入的ID冲突(请注意,AUTO-INCREMENT
计数器将在步骤后返回到其正确的值4)。不幸的是,无法锁定表并截断它。但我们可以(某种方式)使用RENAME
解决 限制。
使用TRUNCATE
1. RENAME TABLE my_table TO my_table_work;
2. CREATE TABLE my_table_backup AS
SELECT * FROM my_table_work WHERE my_date>DATE_SUB(NOW(), INTERVAL 1 MONTH);
3. TRUNCATE my_table_work;
4. LOCK TABLE my_table_work WRITE, my_table_backup WRITE;
5. INSERT INTO my_table_work SELECT * FROM my_table_backup;
6. UNLOCK TABLES;
7. RENAME TABLE my_table_work TO my_table;
8. DROP TABLE my_table_backup;
这应该是完全安全且非常快的。唯一的问题是其他进程会看到表my_table
消失几秒钟。这可能会导致在各处的日志中显示错误。所以这是一个安全的解决方案,但它“很吵”。
免责声明:我不是MySQL专家,因此这些解决方案实际上可能很糟糕。我能提供的唯一保证就是它对我来说很好。如果有专家可以评论这些解决方案,我将不胜感激。
答案 2 :(得分:1)
作为对您问题的回答: &#34;我想重置所有数据并在表格中保留最近30天。&#34;
你可以创建一个活动。查看https://dev.mysql.com/doc/refman/5.7/en/event-scheduler.html
例如:
CREATE EVENT DeleteExpiredLog
ON SCHEDULE EVERY 1 DAY
DO
DELETE FROM log WHERE date < DATE_SUB(NOW(), INTERVAL 30 DAY);
将在您的表格中进行每日清理,保留最近30天的数据
答案 3 :(得分:0)
您可以使用datapump简单地使用查询子句导出表,并使用table_exists_action = replace子句将其导回。它会掉落并重新创建你的桌子,花费的时间更少。请在实施前阅读。