如何使用Doctrine 2截断表格?

mur*_*rze 32 php mysql doctrine-orm nativequery

我假设我需要构建一个本机查询来使用Doctine2截断表.

$emptyRsm = new \Doctrine\ORM\Query\ResultSetMapping();
$sql = 'TRUNCATE TABLE Article';
$query = em()->createNativeQuery($sql, $emptyRsm);
$query->execute();
Run Code Online (Sandbox Code Playgroud)

这给出了错误

SQLSTATE[HY000]: General error
Run Code Online (Sandbox Code Playgroud)

我需要更改为我的代码才能使其工作?

cmt*_*cmt 84

小心截断表

注意在任何RDBMS中截断表,特别是如果要将显式事务用于提交/回滚功能.


DDL语句执行隐式提交

截断表语句是数据定义语言(DDL)语句,因此截断表语句COMMIT在执行时触发对数据库的隐式.如果执行TABLE TRUNCATE,则数据库隐含承诺-即使TABLE TRUNCATE是内START TRANSACTION声明-你的表将被截断和ROLLBACK不会恢复.

因为truncate table语句执行隐式提交,所以Maxence的答案没有按预期执行(但它没有错,因为问题是"如何截断表").他的答案没有按预期执行,因为它截断了一个try块中的表,并假设catch如果出现问题,可以在块中恢复该表.这是一个不正确的假设.


其他用户对此主题的评论和经验

ChrisAelbrecht无法使Maxence的解决方案正常工作,因为即使truncate table语句在显式事务中,您也无法回滚truncate table语句.

不幸的是,用户2130519因为提供正确的答案而被投票(-1直到我投票) - 尽管他没有证明他的答案是正确的,这就像在没有展示你的工作的情况下做数学一样.


我的推荐 DELETE FROM

我的建议是使用DELETE FROM.在大多数情况下,它将按照开发人员的预期执行.但是,DELETE FROM也没有缺点 - 你必须明确重置表的自动增量值.要重置表的自动增量值,必须使用另一个DDL语句ALTER TABLE- 再次,不要ALTER TABLEtry块中使用.它不会按预期工作.

如果你想要何时应该使用DELETE FROMvs的提示,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');
Run Code Online (Sandbox Code Playgroud)


如何删除具有回滚/提交功能的表.

但是,如果您想要回滚/提交功能,则必须使用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();
}
Run Code Online (Sandbox Code Playgroud)

如果您需要重置自动增量值,请记得调用ALTER TABLE <tableName> AUTO_INCREMENT = 1.

  • 只是因为我不得不谷歌:$ con> exec('ALTER TABLE'.$ cmd-> getTableName().'AUTO_INCREMENT = 1;'); (6认同)

Max*_*nce 38

这是我正在使用的代码:

$cmd = $em->getClassMetadata($className);
$connection = $em->getConnection();
$dbPlatform = $connection->getDatabasePlatform();
$connection->beginTransaction();
try {
    $connection->query('SET FOREIGN_KEY_CHECKS=0');
    $q = $dbPlatform->getTruncateTableSql($cmd->getTableName());
    $connection->executeUpdate($q);
    $connection->query('SET FOREIGN_KEY_CHECKS=1');
    $connection->commit();
}
catch (\Exception $e) {
    $connection->rollback();
}
Run Code Online (Sandbox Code Playgroud)

  • 更简单的mysql版本`$ em-> getConnection() - > query('START TRANSACTION; SET FOREIGN_KEY_CHECKS = 0; TRUNCATE table1; TRUNCATE table2; SET FOREIGN_KEY_CHECKS = 1; COMMIT;')` (4认同)

小智 12

或者你可以试试这个:

$this->getEm()->createQuery('DELETE AcmeBundle:Post p')->execute();
Run Code Online (Sandbox Code Playgroud)

如果你有关系,你应该小心处理链接的实体.

  • 删除表中的所有记录与截断表不同. (5认同)