Я предполагаю, что мне нужно создать собственный запрос для обрезания таблицы с помощью Doctine2.
$emptyRsm = new \Doctrine\ORM\Query\ResultSetMapping(); $sql = 'TRUNCATE TABLE Article'; $query = em()->createNativeQuery($sql, $emptyRsm); $query->execute();
Это дает ошибку
SQLSTATE[HY000]: General error
Что мне нужно изменить для моего кода, чтобы сделать эту работу?
Остерегайтесь усечения таблиц в любой СУБД, особенно если вы хотите использовать явные транзакции для функций фиксации / отката.
Операторы таблицы обрезания – это операторы языка определения данных (DDL), и, поскольку такие инструкции таблицы усечения запускают неявный COMMIT
в базу данных после их выполнения . Если вы выполняете TABLE TRUNCATE
тогда база данных неявно передается – даже если TABLE TRUNCATE
находится в инструкции START TRANSACTION
– ваша таблица будет усечена, а ROLLBACK
не восстановит ее.
Поскольку инструкции таблицы truncate выполняют неявные коммиты, ответ Maxence не выполняется так, как ожидалось (но это не так, потому что вопрос был «как обрезать таблицу»). Его ответ не выполняется так, как ожидалось, потому что он обрезает таблицу в блоке try
и предполагает, что таблица может быть восстановлена в блоке catch
, если что-то пойдет не так. Это неверное предположение.
ChrisAelbrecht не смог заставить решение Maxence работать должным образом, потому что вы не можете отменить инструкцию таблицы truncate, даже если инструкция таблицы truncate находится в явной транзакции.
user2130519, к сожалению, был downvoted (-1 до тех пор, пока я не был поддержан) для обеспечения правильного ответа – хотя он сделал это, не оправдывая свой ответ, который похож на математику, не показывая вашу работу.
DELETE FROM
Моя рекомендация – использовать DELETE FROM
. В большинстве случаев он будет выполняться по мере того, как ожидает разработчик. Но DELETE FROM
не имеет недостатков – вы должны явно сбросить значение автоматического приращения для таблицы. Чтобы сбросить значение автоматического увеличения для таблицы, вы должны использовать другой оператор DDL – ALTER TABLE
– и, опять же, не используйте ALTER TABLE
в блоке try
. Он не будет работать так, как ожидалось.
Если вам нужны подсказки, когда вы должны использовать DELETE FROM
vs TRUNCATE
см. « Плюсы и минусы» TRUNCATE vs 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
.
Вот код, который я использую:
$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(); }
Или вы можете просто попробовать это:
$this->getEm()->createQuery('DELETE AcmeBundle:Post p')->execute();
Если у вас есть отношения, вы должны быть осторожны, чтобы обрабатывать связанные объекты.