12
votes

Perl DBI Insérez plusieurs lignes à l'aide de la capacité d'insertion multiple mySQL Native.

Quelqu'un a-t-il déjà vu un module de type DBI pour Perl qui capitalise, facilement, sur la syntaxe multi-inserts de MySQL

Insérer dans les valeurs TBL (COL1, COL2, COL3) (1,2,3), (4,5,6), ... ?

Je n'ai pas encore trouvé d'interface qui me permet de le faire. La seule chose que j'ai trouvée est en boucle dans mon tableau. Cette méthode semble beaucoup moins optimale vs jetant tout en une seule ligne et à laisser mysql la gérer. Je n'ai pas trouvé aucune documentation par exemple, c'est-à-dire Google qui éclaire à ce court-circuit de rouler mon propre code pour le faire.

tia


1 commentaires

Donc, ce que j'ai fini par faire était d'utiliser DBIX :: Simple avec SQL :: Résumé. C'est pourquoi je n'ai pas décidé lequel d'entre eux d'utiliser comme réponse acceptée, pourtant :) ... Il suffit de vous laisser les deux savoir. J'apprécie toute votre aide, cependant.


3 Réponses :


12
votes

Il y a deux approches. Vous pouvez insérer (?, ?,?) Code> Un certain nombre de fois en fonction de la taille de la matrice. La manipulation de texte serait quelque chose comme: xxx pré>

puis aplatir la matrice pour appeler exécuter () code>. J'éviterais de cette façon en raison de la chaîne épineuse et de la manipulation de la matrice qui doit être faite. P>

L'autre moyen est de commencer une transaction, puis d'exécuter une seule instruction insert plusieurs fois. P>

my $sql = 'INSERT INTO tbl (col1, col2, col3)';
$dbh->{AutoCommit} = 0;
my $sth = $dbh->prepare_cached( $sql );
$sth->execute( @$_ ) for @array;
$sth->finish;
$dbh->{AutoCommit} = 1;


4 commentaires

C'est ce que Execute_array dans DBI est pour. Aussi à l'aide de préparer_pare_cached ici ne fait aucune différence, car vous ne vous êtes préparé qu'une fois que cet exemple pourrait aussi bien être un simple préparation.


@boHica - Je considère préparer_cached () pour être une bonne pratique standard. Dans un script autonome, cela ne compte pas particulièrement. Dans un environnement persistant, cela aidera aux invocations futures. Pourrait aussi bien le faire hors d'habitude.


Seul problème avec ceci est que si vous avez des lots et beaucoup de données à insérer, mes tests montrent que le (?,?,?), (?,?) .... Solution est plusieurs fois (> 10 fois) plus rapidement que plusieurs exécutes. :-(


La deuxième variante n'a pas fonctionné pour moi à Mariadb jusqu'à ce que j'ai ajouté "valeurs (?,?)" À la fin de SQL.



9
votes

Si DBD :: MySQL pris en charge DBI's Execute_For_Fetch (voir DBI's Execute_Array et Execute_ForaCetch) Il s'agit du scénario d'utilisation typique, c'est-à-dire que vous disposez de plusieurs lignes d'insertions / mises à jour / suppressions disponibles maintenant et que vous souhaitez les envoyer en une fois (ou en lots ). Je ne sais pas si le client MySQL Libs prend en charge l'envoi de plusieurs lignes de paramètres liés en une seule fois, mais la plupart des autres libs de la base de données font et peuvent tirer parti de DBI's Execute_array / Execute_For_Fetch. Malheureusement, peu de DBD implémentent réellement exécutant_array / exécute_for_fetch et s'appuie sur DBI la implémentant une ligne à la fois.


0 commentaires

1
votes

Jim, Frezik l'a. C'est probablement le plus optimal: xxx


4 commentaires

Je ne suis pas d'accord. Le plus optimal serait d'envoyer des lots de lignes en une fois comme ODBC et Oracle peut faire. Cependant, je ne connais pas MySQL / DBD :: MySQL peut le faire pour le moment. Si DBD :: MySQL implémentée exécutant_for_fetch / Execute_array et le client MySQL Libs supporté l'envoi de lots ou de lignes de paramètres en une fois, cela serait sans aucun doute plus rapide.


et BTW, cet appel à la fin de la fin ne doit pas être requis et est une mauvaise pratique - Lisez sur la POD pour la méthode de l'arrivée.


@boHica - à partir du gousson DBI: "Lorsque toutes les données ont été récupérées à partir d'une instruction SELECT, le pilote appelle automatiquement la finition pour vous." Nous faisons une insertion plutôt que de sélectionner. Ce n'est pas clair pour moi des docs si cela est toujours nécessaire dans ce cas. Merci d'avoir apporté cela, cependant, car la plupart des tutoriels DBI vous permettent d'utiliser toujours terminé () , et il est clair des docs que ce n'est pas correct.


Aussi de la gousse DBI "Vous n'avez presque certainement pas besoin d'appeler cette méthode." et "la méthode d'arrivée aurait dû être appelée Discard_Pending_Rows."