截断条件

Sha*_*500 37 mysql sql truncate

truncate - >这会重置整个表,有没有办法通过truncate来重置特定的记录/检查条件.

例如:我想重置所有数据并在表格中保留最近30天.

谢谢.

cee*_*yoz 60

不,TRUNCATE是全有还是全无.你可以做到DELETE FROM <table> WHERE <conditions>但是这会失去速度优势TRUNCATE.


Min*_*ark 29

简短的回答是没有:MySQL的不能让你一个补充WHERE条款的TRUNCATE声明.这是MySQL关于该TRUNCATE声明的文档.

但好消息是你可以(有点)解决这个限制.

使用简单,安全,清洁但缓慢的解决方案 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;
Run Code Online (Sandbox Code Playgroud)

这些LOCKUNLOCK声明不是强制性的,但它们会加快速度并避免潜在的死锁.

不幸的是,如果你的表很大,这将是非常慢的...并且因为你正在考虑使用该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;
Run Code Online (Sandbox Code Playgroud)

不幸的是,如果其他进程同时在表中插入记录,则此解决方案有点不安全:

  • 在步骤1和2之间插入的任何记录都将丢失
  • 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;
Run Code Online (Sandbox Code Playgroud)

这应该是完全安全且非常快的.唯一的问题是其他进程会看到表my_table消失几秒钟.这可能会导致在各处的日志中显示错误.所以这是一个安全的解决方案,但它"嘈杂".

免责声明:我不是MySQL专家,因此这些解决方案实际上可能很糟糕.我能提供的唯一保证就是它对我来说很好.如果有专家可以评论这些解决方案,我将不胜感激.

  • 好的答案和克服限制的好方法。谢谢。 (2认同)