谨防截断表
小心在任何 RDBMS 中截断表,特别是如果您想使用显式事务来实现提交/回滚功能。请阅读此答案的“我的建议”。
DDL 语句执行隐式提交
截断表语句是数据定义语言 (DDL) 语句,因此截断表语句在执行时触发对数据库的隐式COMMIT
。如果您执行 aTABLE TRUNCATE
那么数据库将被隐式提交——即使TABLE TRUNCATE
它在一个START TRANSACTION
语句中——你的表将被截断并且 a不会ROLLBACK
恢复它。
因为 truncate table 语句执行隐式提交,所以 Maxence 的答案没有按预期执行(但这并没有错,因为问题是“如何截断表”)。他的回答没有按预期执行,因为它截断了try
块中的表,并假设catch
如果出现问题,可以在块中恢复表。这是一个不正确的假设。
其他用户在此线程中的评论和经验
ChrisAelbrecht 无法让 Maxence 的解决方案正常工作,因为您无法回滚 truncate table 语句,即使 truncate table 语句位于显式事务中。
不幸的是,user2130519 因为提供了正确的答案而被否决(-1 直到我投了赞成票)——尽管他这样做并没有证明他的答案是正确的,这就像在没有展示你的工作的情况下做数学一样。
我的推荐DELETE FROM
我的建议是使用DELETE FROM
. 在大多数情况下,它将按照开发人员的预期执行。但是,DELETE FROM
也不是没有缺点——您必须明确地重置表的自动增量值。要重置表的自动增量值,您必须使用另一个 DDL 语句ALTER TABLE
——并且再次,不要ALTER TABLE
在您的try
块中使用。它不会按预期工作。
如果您想了解何时应该使用DELETE FROM
vs的提示,TRUNCATE
请参阅TRUNCATE 与 DELETE FROM 的优缺点。
如果你真的必须,这里是如何截断
现在,说了这么多。如果您真的想使用 Doctrine2 截断表格,请使用:(以下是 Maxence 正确截断表格的答案部分)
$cmd = $em->getClassMetadata($className);
$connection = $em->getConnection();
$dbPlatform = $connection->getDatabasePlatform();
$connection->query('SET FOREIGN_KEY_CHECKS=0');
$q = $dbPlatform->getTruncateTableSql($cmd->getTableName());
$connection->executeUpdate($q);
$connection->query('SET FOREIGN_KEY_CHECKS=1');
如何删除具有回滚/提交功能的表。
但是,如果您想要回滚/提交功能,则必须使用DELETE FROM
:(以下是 Maxence 答案的修改版本。)
$cmd = $em->getClassMetadata($className);
$connection = $em->getConnection();
$connection->beginTransaction();
try {
$connection->query('SET FOREIGN_KEY_CHECKS=0');
$connection->query('DELETE FROM '.$cmd->getTableName());
// Beware of ALTER TABLE here--it's another DDL statement and will cause
// an implicit commit.
$connection->query('SET FOREIGN_KEY_CHECKS=1');
$connection->commit();
} catch (\Exception $e) {
$connection->rollback();
}
如果需要重置自动增量值,记得调用ALTER TABLE <tableName> AUTO_INCREMENT = 1
.