web-dev-qa-db-fra.com

Comment insérer un tableau dans une seule déclaration MySQL Prepared avec PHP et AOP

Lors d'une inscription en ligne, un client peut sélectionner un certain nombre de programmes pour lesquels il a choisi de s'inscrire. Ces programmes sont des entiers à trois chiffres et sont stockés dans un tableau.

Par exemple:

Je veux m'inscrire aux programmes 155, 165, 175 et 185.

Mon tableau est configuré aussi simplement que:

$data = array();

$data[] = 155;

$data[] = 165;

$data[] = 175;

$data[] = 185;

Lorsque vient le temps d'insérer ces informations dans la table associée, j'inclus également des éléments supplémentaires provenant de l'autre partie de l'inscription:

Par exemple, si je faisais une instruction d'insertion de programme SINGLE, cela ressemblerait à ceci:

$stmt = $db->prepare("INSERT INTO table SET memberID=?, programID=?, date_added=NOW()");
$stmt->execute(array($memberid, 155));

Je créerais normalement une boucle simple pour le tableau ci-dessus, qui appellerait plusieurs instances de l'instruction SQL et s'exécuterait, par exemple:

for($j = 0; $j < (count($data)-1); $j++) {
   $stmt = $db->prepare("INSERT INTO table SET memberID=?, programID=?, date_added=NOW()");
   $stmt->execute(array($memberid, $data[$j]));
}

Je me rends bien compte que le code ci-dessus est invalide ($ data [$ j]) mais je cherche la bonne façon de faire l'appel.

On m'a aussi déjà dit que la construction d'une seule déclaration SQL dynamique est globalement meilleure que plusieurs appels comme ci-dessus. Mon premier passage serait quelque chose comme:

$sql = array(); 
foreach( $data as $row ) {
    $sql[] = '("'.$memberid.'", "'.$row[$j].'", NOW()")';
}
mysql_real_query('INSERT INTO table (memberid, programid) VALUES '.implode(',', $sql));

mais avec AOP, je ne sais pas trop comment cela fonctionne, en particulier avec des espaces réservés (?).

Aucune suggestion?

15
JM4

Vous pouvez créer la requête par programme ...:

$sql = 'INSERT INTO table (memberID, programID) VALUES ';
$insertQuery = array();
$insertData = array();
foreach ($data as $row) {
    $insertQuery[] = '(?, ?)';
    $insertData[] = $memberid;
    $insertData[] = $row;
}

if (!empty($insertQuery)) {
    $sql .= implode(', ', $insertQuery);
    $stmt = $db->prepare($sql);
    $stmt->execute($insertData);
}
27
ircmaxell

2 solutions

// multiple queries
$stmt = $pdo->prepare('INSERT INTO table SET memberID=:memberID, programID=:programID, date_added=NOW()');
$data = array(155, 165, 175, 185);
foreach($data as $d) {
    $stmt->execute(array(':memberID' => $memberid, ':programID' => $d));
}

Et

// one query
$data = array(155, 165, 175, 185);
$values = array();
foreach($data as $d) {
    $values[] = sprintf('(%d, %d, NOW())', $d, $memberid);
}
$sql = sprintf('INSERT INTO table (memberID, programID, date_added) VALUES %s', implode (', ', $values));
$pdo->exec($sql);
9
Xavier Barbosa

Ce que vous cherchez, c'est comment faire une insertion BULK, c'est plus lié à SQL qu'à PDO lui-même.

Il vous suffit de faire exactement la même chose qu'avec * _query, de construire votre requête d'insertion en bloc et votre tableau de paramètres côte à côte.

$placeholder = array();
$values = "?, ?, ?, ...";
$args = array();
foreach ($arrays as $array) {
  $placeholder[] = $value;
  $args[] = $array['col1'];
  $args[] = $array['col2'];
  $args[] = $array['col3'];
  ...
}    
$sql = "INSERT INTO table (col1, col2, ... ) VALUES ("
     . implode('), (', $placeholder)
     . ")"; 
$stmt = $db->prepare($sql);
$db->execute($sql, $args);

C'est un algorithme moche mais fonctionnel, je pense.

0
Pierre