1
votes

Insertion en vrac Cakephp 3.0

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 commentaires

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.


4 Réponses :


0
votes

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!


0 commentaires

1
votes
$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.

2 commentaires

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.



1
votes
  • Lorsque vous effectuez une insertion "groupée" avec 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>
  • Dans ORM, votre application effectue d'abord la validation des données, puis crée une requête SQL pour l'entité actuelle. Pas de grande différence de vitesse.

1 commentaires

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



1
votes

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


0 commentaires