Wie kann ich Arrays von Werten in der Datenbank speichern?

8

Ich versuche, mehrere Werte aus einem Textbereich in einer Datenbanktabelle zu speichern.

Ich benutze den folgenden Code, aber ich denke, es ist der falsche Weg.

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

Gibt es einen anderen Weg, um das gleiche Ergebnis zu erzielen?

Mohamed Ibrahim
quelle

Antworten:

15

Ich würde den folgenden Code verwenden.

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

Alternativ können Sie den folgenden Code verwenden.

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

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

$query->execute();

Bei MySQL verwendet die Abfrage die mehrwertige Syntax.

Bei anderen Datenbanken sind die ausgeführten Abfragen eine für jeden Aufruf von $query->values(), die in eine Transaktion eingeschlossen sind. Dies bedeutet, dass die Abfragen zurückgesetzt werden, wenn eine davon fehlschlägt. Tatsächlich ist der von InsertQuery :: execute () ausgeführte Code der folgende.

  // 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;
  }

Kurz gesagt, ich würde den von Ihnen verwendeten Code verwenden, wenn die eingefügten Werte unabhängig voneinander sind. Ich würde den Code verwenden, den ich gezeigt habe, wenn die Werte voneinander abhängen.

In Ihrem Fall sind die E-Mails unabhängig voneinander. Wenn Sie das zweite von mir gezeigte Snippet verwenden würden, enthält die Datenbanktabelle alle Werte, wenn die Unterabfrage nicht fehlschlägt, oder keine, wenn eine einzelne Unterabfrage fehlschlägt.

Sie könnten auch verwenden drupal_write_record(), obwohl ich die anderen Schnipsel sehr bevorzuge.

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

Ich sehe jedoch keinen Profi darin, dieses Snippet zu verwenden.

Referenz

kiamlaluno
quelle
1
Es tut mir leid, was ist mit dem auf dieser Dokumentationsseite gezeigten "Multi-Insert-Formular". Geben Sie 1 Array von $valuesund rufen Sie nur 1 auf execute(). drupal.org/node/310079 Dies wird beispielsweise bei der Erstellung von Standardblöcken für Standardprofile verwendet.
Tenken
2
Es ist wahr, Sie können ->values(...)so oft anrufen, wie Sie möchten, InsertQueryund es wird eine Abfrage wieINSERT INTO x (field1, field2) VALUES ('val1', 'val2'), ('val3', 'val4'), etc
Clive
2
Okay, jetzt habe ich mich daran erinnert, warum ich Folgendes verworfen habe $query->values(): In den meisten Fällen sind die Werte, die mein Code einfügt, unabhängig voneinander, und ich möchte nicht, dass ein Fehler mit einem Wert ein Rollback der anderen Werte verursacht.
Kiamlaluno
3

Dies ist eine ähnliche Version wie Ihr Code, aber eine bessere Leistung. Sie möchten execute () wirklich nicht tausendmal aufrufen, sondern müssen es nur einmal aufrufen.

Referenz

$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();
donutdan4114
quelle
Hat für mich funktioniert, außer dass es OOM-Fehler auslösen würde, wenn die Anzahl der Zeilen in meinem Fall zu groß ist (10.000). Also habe ich das in Chargen von 1000 oder weniger aufgeteilt, um dieses Problem zu lösen.
Eduardo Chongkan