如何在不破坏引用完整性的情况下删除所有数据


How to delete all data without breaking referential integrity using Doctrine?

我为Symfony 1.4编写了一个单元测试插件,它试图自动管理数据库,类似于Django的测试框架(在测试之间销毁和重建数据库)。

在第一次测试运行之前销毁和重建数据库是有意义的,因为模式可能在开发过程中发生了变化,并且让开发人员手动保持测试数据库与模型同步将是可怕的虐待。

然而,在第一次测试运行之后,我发现删除所有数据通常更快,这将是一个相当简单的任务,除了外键的问题,它要求以正确的顺序删除数据。

对于MySQL,这不是问题;简单的SET FOREIGN_KEY_CHECKS = 0,你可以破坏引用完整性到你的核心内容(当然,直到SET FOREIGN_KEY_CHECKS = 1的时间,但在这种情况下,将没有数据留下,所以MySQL没有什么可抱怨的)。

但是这只在测试数据库使用MySQL时有效。对于任何其他DBMS(尤其是Sqlite),这将惨败。

Doctrine 1.2是否提供了一种删除每个表中所有数据的方法,或者是否有一种"遵循"关系的方法(即,确定哪些表有外键并首先从它们中删除)?

我将使用Doctrine dal并首先查找外键。看一下Doctrine关于Schema-Manager的DBAL文档,它的相关API文档以及ForeignKeyConstraint中提供的方法。

EDIT:对于doctrine 1.2,似乎有类似的方法来检索这里记录的外键。

查找所有外键约束,并根据约束让代码决定以何种顺序删除数据

Doctrine_Data->purge()利用Doctrine_Connection_UnitOfWork->buildFlushTree()来做我想要完成的事情。

有点道理,看到Doctrine_Data_Import->doImport()(即symfony doctrine:data-load)已经提供了我试图重新发明的功能…我怎么会错过那个呢?: P

另一种方法是使用事务。

在测试开始时启动事务,然后在测试完成后发出回滚。数据库将删除测试期间创建的所有数据。

但是,必须小心确保实际依赖于事务的测试代码继续工作。

这是Django的测试框架的工作方式:

class TestCase(TransactionTestCase):
    """
    Does basically the same as TransactionTestCase, but surrounds every test
    with a transaction, monkey-patches the real transaction management routines to
    do nothing, and rollsback the test transaction at the end of the test. You have
    to use TransactionTestCase, if you need transaction management inside a test.
    """