Comment tronquer une table en utilisant la Doctrine 2?
je suppose que je dois construire une requête native pour tronquer une table en utilisant Doctine2.
$emptyRsm = new DoctrineORMQueryResultSetMapping();
$sql = 'TRUNCATE TABLE Article';
$query = em()->createNativeQuery($sql, $emptyRsm);
$query->execute();
cela donne l'erreur
SQLSTATE[HY000]: General error
Que dois-je changer à mon code pour que cela fonctionne?
4 réponses
attention aux Tables tronquées
méfiez-vous de tronquer les tables dans n'importe quel SGBDR, surtout si vous voulez utiliser des transactions explicites pour la fonctionnalité de commit/rollback.
instructions DDL effectuer un implicite-commit
les énoncés de table tronqués sont des énoncés de définition de données (DDL), et en tant que tels les énoncés de table tronqués déclenchent un implicite COMMIT
à la base de données lors de leur exécution . Si vous exécutez un TABLE TRUNCATE
alors la base de données est implicitement engagée à--même si le TABLE TRUNCATE
est dans un START TRANSACTION
statement--votre table sera tronquée et un ROLLBACK
will pas le restaurer.
parce que les déclarations de table tronquées effectuent des commits implicites, la réponse de Maxence ne fonctionne pas comme prévu (mais ce n'est pas mal, parce que la question était "comment tronquer un tableau"). Sa réponse ne fonctionne pas comme prévu parce qu'elle tronque la table dans un bloc try
, et suppose que la table peut être restaurée dans le bloc catch
, si quelque chose va mal. C'est une hypothèse erronée.
commentaires et expériences d'autres utilisateurs dans ce fil de discussion
ChrisAelbrecht n'a pas pu obtenir la solution de Maxence pour fonctionner correctement parce que vous ne pouvez pas faire reculer un énoncé de table tronquée, même si l'énoncé de table tronquée est dans une transaction explicite.
user2130519, malheureusement, a été rétrogradé (-1 jusqu'à ce que je rétrograde) pour fournir la bonne réponse--bien qu'il l'ait fait sans justifier sa réponse, qui est comme faire des mathématiques sans montrer votre travail.
ma recommandation DELETE FROM
ma recommandation est d'utiliser DELETE FROM
. Dans la plupart des cas, il fonctionnera comme le développeur. Mais, DELETE FROM
ne vient pas sans inconvénients non plus--vous devez explicitement réinitialiser la valeur d'incrément automatique pour la table. Pour réinitialiser la valeur d'incrément automatique pour la table, vous devez utiliser une autre instruction DDL-- ALTER TABLE
--et, encore une fois, n'utilisez pas ALTER TABLE
dans votre bloc try
. Il ne fonctionnera pas comme prévu.
si vous voulez des conseils sur quand vous devez utiliser DELETE FROM
vs TRUNCATE
voir pour & contre de tronquer vs Supprimer de .
Si vous devez vraiment, voici comment tronquer
maintenant, avec tout ce qui est dit. Si vous voulez vraiment tronquer une table en utilisant Doctrine2, utilisez ceci: (ci-dessous est la partie de la réponse de Maxence qui tronque correctement une table)
$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');
comment supprimer une table avec fonction rollback/commit.
mais, si vous voulez la fonctionnalité rollback/commit, vous devez utiliser DELETE FROM
: (ci-dessous est une version modifiée de la réponse de 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();
}
si vous devez réinitialiser la valeur d'incrément automatique, n'oubliez pas d'appeler ALTER TABLE <tableName> AUTO_INCREMENT = 1
.
voici le code que j'utilise:
$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();
}
ou vous pourriez juste essayer ceci:
$this->getEm()->createQuery('DELETE AcmeBundle:Post p')->execute();
si vous avez des relations, vous devez faire attention aux entités liées.
il s'agit d'un exemple de méthode de tronçonnage de trait dans les essais unitaires.
/**
* Cleanup any needed table abroad TRUNCATE SQL function
*
* @param string $className (example: App\Entity\User)
* @param EntityManager $em
* @return bool
*/
private function truncateTable (string $className, EntityManager $em): bool {
$cmd = $em->getClassMetadata($className);
$connection = $em->getConnection();
$connection->beginTransaction();
try {
$connection->query('SET FOREIGN_KEY_CHECKS=0');
$connection->query('TRUNCATE TABLE '.$cmd->getTableName());
$connection->query('SET FOREIGN_KEY_CHECKS=1');
$connection->commit();
$em->flush();
} catch (\Exception $e) {
try {
fwrite(STDERR, print_r('Can\'t truncate table ' . $cmd->getTableName() . '. Reason: ' . $e->getMessage(), TRUE));
$connection->rollback();
return false;
} catch (ConnectionException $connectionException) {
fwrite(STDERR, print_r('Can\'t rollback truncating table ' . $cmd->getTableName() . '. Reason: ' . $connectionException->getMessage(), TRUE));
return false;
}
}
return true;
}
s'il vous Plaît noter, que si vous n'utilisez pas $em->flush()
, vous avez un risque d'avoir un problème avec la requête suivante à la doctrine.
vous devez également comprendre que si vous utilisez cette méthode dans un contrôleur, vous devez changer les lignes fwrite(STDERR, print_r(...
en quelque chose que votre service logger peut utiliser.