В Cakephp 3.0 для сохранить много записей указано использовать функцию saveMany
.
https://book.cakephp.org/3.0/en/orm/saving-data.html#saving-multiple-entities
Однако приведенный выше оператор вставки отправки по одному.
Мне нужно обновить несколько тысяч записей одновременно, поэтому я хотел бы использовать пакетная вставка моих записей, а не вставлять их по одной.
Чтобы проверить это, я попробовал saveMany
поведение. Я проверил свое querys.log
, похоже, что использование saveMany
не вставляет мой запрос в пакет, а действительно вставляет его один за другим.
Другими словами, я хотел бы иметь это:
INSERT INTO mytable (id, code) VALUES ('123', 'code_a'), ('123', 'code_b'), ('123', 'code_c'), ('123', 'code_d'), ('123', 'code_e');
Но вместо этого было выполнено следующее
INSERT INTO mytable (id, code) VALUES ('123', 'code_a')
INSERT INTO mytable (id, code) VALUES ('123', 'code_b')
INSERT INTO mytable (id, code) VALUES ('123', 'code_c')
INSERT INTO mytable (id, code) VALUES ('123', 'code_d')
INSERT INTO mytable (id, code) VALUES ('123', 'code_e')
Итак, мой вопрос, как я могу сделать объемная вставка в Тортphp 3.0
Примечание. Я провел небольшое исследование и обнаружил, что функция saveAll
была в Тортphp 2.0 и могла выполнять пакетную обработку (предположительно), но, к сожалению, такой функции нет в версии 3.0.
🤔 А знаете ли вы, что...
Фреймворк обладает встроенной системой логирования и отладки приложений.
Поскольку мне действительно нужна массовая вставка, теперь мне нужно использовать традиционное выполнение для обработки моего запроса:
<?php
$sql = "INSERT INTO mytable ";
$binding = [];
$insertSql = [];
foreach($myEntitys as $i => $myEntity){
$myEntityArray = $myEntity->toArray();
$myEntityArrayKeys = array_keys($myEntityArray);
if ($i === 0){
$sql .= "(";
$sql .= implode(",", $myEntityArrayKeys);
$sql .= ")";
}
$singleInsertSql = [];
foreach($myEntityArrayKeys as $key) {
$value = $myEntityArray[$key];
$singleInsertSql[] = "?";
$binding[] = $value;
}
$insertSql[] = "(" . implode(",", $singleInsertSql) . ")";
}
$sql .= " VALUES " . implode(",", $insertSql);
$connection = ConnectionManager::get('default');
$connection->execute($sql, $binding);
Это делает работу, но очень уродливо, надеюсь, кто-то может опубликовать более собственный метод торта, спасибо!
$mytable = TableRegistry::getTableLocator()->get('ModelNameOfTable');
foreach ($myEntitys as $row)
{
$record = $mytable->newEntity();
foreach ($row as $column => $value)
{
$record->{$column} = $value;
}
if ($mytable->save($record))
{
$id = $record->id; // for checking if needed
}
}
Что-то вроде этого должно сделать это.
Просто ссылка: https://book.cakephp.org/3.0/en/orm/saving-data.html
ХОТЯ, если ваша таблица довольно сложна и вам потребуется много перекрестных ссылок/проверок полей, создание собственного пользовательского выполнения SQL, как вы, может быть более подходящим.
Идеал использования ORM и моделей состоит в том, чтобы обеспечить возможность совместного использования кода на разных платформах (моделях) баз данных. В вашем случае вы пишете что-то для «передачи» данных, а не для обмена.
INSERT INTO mytable (id, code) VALUES ('123', 'code_a'), ('123', 'code_b'), ('123', 'code_c'), ('123', 'code_d'), ('123', 'code_e');
, вы отправляете все данные вставки в одном запросе sql без проверки, но сама база данных в фоновом режиме вставляется одна за другой.