Come posso salvare matrici di valori nel database?


8

Sto cercando di salvare più valori da un'area di testo a una tabella di database.

Uso il seguente codice, ma ritengo che sia sbagliato.

foreach ($user_emails as $key => $value) {
  $insert_banned_emails = db_insert('banned_users');
  $insert_banned_emails
    ->fields(array(
      'email' => $value,
    ))
    ->execute();
}

Esiste un modo diverso per ottenere lo stesso risultato?

Risposte:


15

Vorrei usare il seguente codice.

foreach ($user_emails as $value) {
  $query = db_insert('banned_users');
  $query->fields(array('email' => $value))->execute();
}

In alternativa, è possibile utilizzare il seguente codice.

$query = db_insert('banned_users')->fields(array('email'));

foreach ($user_emails as $value) {
  $query->values(array('email' => $value));
}

$query->execute();

Con MySQL, la query utilizza la sintassi multi-valore.

Con altri database, le query eseguite saranno una per ogni chiamata a $query->values(), racchiuse in una transazione. Ciò significa che le query verranno ripristinate quando una di esse fallisce. In effetti, il codice eseguito da InsertQuery :: execute () è il seguente.

  // Each insert happens in its own query in the degenerate case. However,
  // we wrap it in a transaction so that it is atomic where possible. On many
  // databases, such as SQLite, this is also a notable performance boost.
  $transaction = $this->connection->startTransaction();

  try {
    $sql = (string) $this;
    foreach ($this->insertValues as $insert_values) {
      $last_insert_id = $this->connection->query($sql, $insert_values, $this->queryOptions);
    }
  }
  catch (Exception $e) {
    // One of the INSERTs failed, rollback the whole batch.
    $transaction->rollback();
    // Rethrow the exception for the calling code.
    throw $e;
  }

In breve, vorrei usare il codice che stai usando se i valori inseriti sono indipendenti l'uno dall'altro; Vorrei usare il codice che ho mostrato quando i valori dipendono l'uno dall'altro.

Nel tuo caso, le e-mail sono indipendenti l'una dall'altra. Se utilizzi il secondo frammento mostrato, la tabella del database conterrà tutti i valori, quando la query secondaria non fallisce o nessuna quando una query secondaria non riesce.

Potresti anche usare drupal_write_record(), anche se preferisco di gran lunga gli altri frammenti.

foreach ($user_emails as $value) {
  drupal_write_record('banned_users', array('email' => $value));
}

Tuttavia, non vedo alcun professionista nell'usare questo frammento.

Riferimento


1
Mi dispiace per quanto riguarda il "Modulo a inserimento multiplo" mostrato in questa pagina della documentazione. Dare 1 matrice di $valuese chiamare solo 1 execute(). drupal.org/node/310079 Viene utilizzato ad esempio nella creazione di blocchi predefiniti di profili standard.
Tenken

2
È vero, puoi chiamare ->values(...)tutte le volte che vuoi su un InsertQuerye preparerà una query del tipoINSERT INTO x (field1, field2) VALUES ('val1', 'val2'), ('val3', 'val4'), etc
Clive

2
Bene, ora ho ricordato il motivo per cui ho scartato usando $query->values(): Nella maggior parte dei miei casi, i valori che il mio codice sta inserendo sono indipendenti l'uno dall'altro e non voglio che un errore con un valore provochi un rollback degli altri valori.
kiamlaluno

3

Questa è una versione simile al tuo codice, ma prestazioni migliori. Non vuoi davvero chiamare execute () mille volte, devi solo chiamarlo una volta.

Riferimento

$insert_banned_emails = db_insert('banned_users')->fields(array('email'));
foreach ($user_emails as $key => $value) {
  $insert_banned_emails->values(array(
    'email' => $value,
  ));               
}
$insert_banned_emails->execute();

Ha funzionato per me, tranne per il fatto che avrebbe generato errori OOM quando il numero di linee è troppo grande (10.000) nel mio caso. Quindi l'ho diviso in lotti di 1000 o meno per risolvere quel problema.
Eduardo Chongkan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.