Подтвердить что ты не робот

Как обрезать таблицу с помощью Doctrine 2?

Я предполагаю, что мне нужно создать собственный запрос для обрезания таблицы с помощью Doctine2.

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

Это дает ошибку

SQLSTATE[HY000]: General error

Что мне нужно изменить для моего кода, чтобы сделать эту работу?

4b9b3361

Ответ 1

Остерегайтесь усеченных таблиц

Остерегайтесь усечения таблиц в любой СУБД, особенно если вы хотите использовать явные транзакции для функций фиксации/отката.


Операторы DDL выполняют неявный-commit

Операторы таблицы обрезания - это формулировки языка определения данных (DDL), и как таковые операторы таблицы truncate запускают неявное 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 также не имеет недостатков - вы должны явно указать reset значение автоматического приращения для таблицы. В reset значение автоматического приращения для таблицы вы должны использовать другой оператор 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 another DDL statement and will cause
    // an implicit commit.
    $connection->query('SET FOREIGN_KEY_CHECKS=1');
    $connection->commit();
} catch (\Exception $e) {
    $connection->rollback();
}

Если вам нужно reset значение автоматического увеличения, не забудьте вызвать ALTER TABLE <tableName> AUTO_INCREMENT = 1.

Ответ 2

Вот код, который я использую:

$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();
}

Ответ 3

Или вы могли бы просто попробовать это:

$this->getEm()->createQuery('DELETE AcmeBundle:Post p')->execute();

Если у вас есть отношения, вы должны быть осторожны, чтобы обрабатывать связанные объекты.