Dans Cakephp 3.0, pour sauvegarder de nombreux enregistrements , il est demandé d'utiliser la fonction saveMany
.
https: //book.cakephp .org / 3.0 / fr / orm / save-data.html # save-multiple-entity
Cependant, la déclaration ci-dessus submit insert une par une .
J'ai besoin de mettre à jour quelques milliers d'enregistrements à la fois, je voudrais donc insérer mes enregistrements par lots au lieu de les insérer un par un.
Pour vérifié ceci J'ai essayé le comportement de saveMany
J'ai inspecté mon querys.log
il semble que l'utilisation de saveMany
n'insère pas ma requête dans un lot, et même insère un par un.
En d'autres termes, j'aimerais avoir ceci:
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')
Mais à la place, ce qui suit a été exécuté
INSERT INTO mytable (id, code) VALUES ('123', 'code_a'), ('123', 'code_b'), ('123', 'code_c'), ('123', 'code_d'), ('123', 'code_e');
Ma question est donc la suivante: comment puis-je faire une insertion en masse dans Cakephp 3.0
Remarque: je fais quelques recherches et voyez qu'une fonction saveAll
était dans Cakephp 2.0 et qu'elle peut effectuer un traitement par lots essing (soi-disant), mais malheureusement, une telle fonction n'est pas présente dans la version 3.0.
4 Réponses :
Parce que j'ai vraiment besoin d'une insertion en masse, je dois maintenant utiliser l'exécution traditionnelle pour gérer ma requête:
<?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);
Cela fait le travail mais c'est très moche, j'espère que quelqu'un peut poster un plus de gâteau méthode native, merci!
$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 } } Something like this should do it.Just reference: https://book.cakephp.org/3.0/en/orm/saving-data.htmlALTHOUGH, if your table is quite complex and you will require a lot cross-referencing / field checking, creating your own custom SQL execution as you did, could easily be more suitable.The ideal of using the ORM and Models is to keep code shareable across different database platforms (models). In your case, you are writing something to "transfer" data rather than share.
Le point clé que je veux atteindre est de rendre le SQL INSERT INTO mytable (id, code) VALUES ('123', 'code_a'), ('123', 'code_b'), ('123', ' code_c '), (' 123 ',' code_d '), (' 123 ',' code_e ');
dont je doute fort que cette méthode le résoudra. Cependant je vais l'essayer tmr quand j'aurai le temps, merci!
vous écrivez quelque chose pour "transférer" des données
Oui, c'est exactement ce que fait ma logique. J'ai besoin d'obtenir beaucoup de données de la base de données, de les traiter, puis de les réinsérer dans une autre base de données, la validation est déjà effectuée avant l'insertion en masse. Merci.
INSERT INTO mytable (id, code) VALUES ('123', 'code_a'), ('123', 'code_b'), ('123', 'code_c '), (' 123 ',' code_d '), (' 123 ',' code_e ');
vous envoyez toutes les données d'insertion dans une requête SQL sans validation, mais la base de données elle-même en arrière-plan insère une par une. < / li>
Merci pour votre contribution, mais dans mes tests, il y a en fait une grande vitesse différente, après que je suis passé de l'utilisation de ma réponse ci-dessous, ma vitesse de requête passe de 30s
à 5s
Les insertions en masse dans cakephp sont assez simples:
<?php $query = $this->MyModel->query(); foreach ($data as $row) { $query ->insert(['column1', 'column2']) ->values([ 'column1' => $row['value1'], 'column2' => $row['value2'] ]); } $query->execute();
book.cakephp.org/3.0/en /orm/query-builder.html#inserting-dat a
Pour info, la méthode de book.cakephp.org/3.0 /en/orm/query-builder.html#inserting-dat a est également inséré un par un, déjà testé. Merci.
Ce n'est pas correct, vous pouvez définir plusieurs ensembles de valeurs comme indiqué dans le deuxième exemple. Cela générera une requête qui utilise plusieurs ensembles de données dans la clause
VALUES
en conséquence.@ndm Oh mec, tu as raison, ta réponse fonctionne! Mes excuses pour les mauvais tests avant la main. Veuillez soumettre une réponse et je l'accepterai, merci.