在MySQL中截断一组表的更快捷方法是什么?

时间:2014-04-18 16:02:29

标签: mysql foreign-keys rename truncate

我正在使用MySql 5.5.37。我试图截断一组表中的数据。我在这里阅读 - Quickest way to delete enormous MySQL table,重新创建/重命名表的速度应该更快,但我收到错误......

SET FOREIGN_KEY_CHECKS=0;
…
CREATE TABLE IF NOT EXISTS new_organization LIKE organization; 
RENAME TABLE organization TO old_t, new_organization TO organization; 
DROP TABLE old_t;

CREATE TABLE IF NOT EXISTS new_organization_address LIKE organization_address; 
RENAME TABLE organization_address TO old_t, new_organization_address TO organization_address; 

ERROR 1025 (HY000): Error on rename of './sbjunit_ebook/organization_address' to './sbjunit_ebook/old_t' (errno: 150)

进一步研究这个问题,它说......

Error in foreign key constraint of table sbjunit_ebook/old_t:
there is no index in referenced table which would contain
the columns as the first columns, or the data types in the
referenced table do not match the ones in table. Constraint:
,
  CONSTRAINT "FK1_ORGANIZTION_ADDRESS" FOREIGN KEY ("ORGANIZATION_ID") REFERENCES "old_t" ("ID") ON DELETE CASCADE ON UPDATE NO ACTION
The index in the foreign key in table is "UK_ORGANIZATION_ADDRESS"

为什么重命名表不更新外键引用?从表组中截断数据的更快方法是什么?

1 个答案:

答案 0 :(得分:0)

重命名表(使用RENAME TABLE语句)不会影响引用该表的外键。引用该表的外键得到更新"只有在他们不受影响的意义上,他们才会失去"。只有表的名称受到影响;引用该表的外键引用并没有丢失。

当您禁用foreign_key_checks时,您实际上是告诉数据库您负责维护数据的完整性。它并没有指示MySQL失去"重命名表时的外键约束定义。

在这种情况下,当删除名为old_t的表时,MySQL假定将重新创建名为old_t的表,并且它将具有合适的索引(列名,列数据类型)现有的外键将参考。它还假设将插入适当的行,以便满足所有外键约束。

(请注意,如果启用了FOREIGN_KEY_CHECKS,则DROP TABLE语句将不会成功,该语句将返回错误。)


清空该表的最快方法实际上是禁用引用该表的外键约束,然后在表上执行TRUNCATE语句。 MySQL将通过创建一个新的空表并删除旧表来实际执行TRUNCATE操作(在封面下)。

您可以对其他表遵循相同的模式。

此时,您将重新启用外键约束。

(MySQL实际上并不支持外键约束的DISABLE / ENABLE;我们必须DROP并添加外键约束。

ALTER TABLE bar DROP 
 FOREIGN KEY (foo_id) ;

ALTER TABLE bar ADD 
  CONSTRAINT FK_bar_foo 
  FOREIGN KEY (foo_id) REFERENCES foo (id) ;

(请注意,在"大"表上创建外键约束可能需要一些时间,但如果表bar为空,则它会非常快。)


<强>更新

可以查询information_schema表以帮助构建外键的DROPADD

保存&#34;重要的是&#34;删除之前的现有外键约束。

此SQL语句适用于生成某些表上的外键约束的DROPADD语句。 (我的所有外键约束都有用户提供的名称,没有系统生成的名称。)您的里程可能会有所不同:

对于引用 mydatabase.mytable

的外键
SELECT CONCAT('ALTER TABLE `',r.constraint_schema,'`.`',r.table_name
             ,'` ADD'
             ,' CONSTRAINT `',r.constraint_name,'`'
             ,' FOREIGN KEY ('
             ,GROUP_CONCAT(CONCAT('`',k.column_name,'`') 
                           ORDER BY k.ordinal_position)
             ,') REFERENCES ',r.referenced_table_name
             ,' ('
             ,GROUP_CONCAT(CONCAT('`',k.referenced_column_name,'`')
                           ORDER BY k.ordinal_position)
             ,')'
             ,' ON UPDATE ',r.update_rule
             ,' ON DELETE ',r.delete_rule
             ,';'
       ) AS add_fk
     , CONCAT('ALTER TABLE `',r.constraint_schema,'`.`',r.table_name
              ,'` DROP FOREIGN KEY '
              ,'`',r.constraint_name,'`'
              ,';'
       ) AS drop_fk
  FROM information_schema.referential_constraints r
  JOIN information_schema.key_column_usage k
       ON k.constraint_schema = r.constraint_schema 
       AND k.table_name  = r.table_name
       AND k.constraint_name = r.constraint_name
 WHERE r.constraint_schema = 'mydatabase'
   AND r.referenced_table_name = 'mytable'
 GROUP BY r.constraint_schema, r.table_name, r.constraint_name ;