値の配列をデータベースに保存するにはどうすればよいですか?


8

textareaからデータベーステーブルに複数の値を保存しようとしています。

以下のコードを使用していますが、間違っているように感じます。

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

同じ結果を得る別の方法はありますか?

回答:


15

次のコードを使用します。

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

または、次のコードを使用することもできます。

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

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

$query->execute();

MySQLでは、クエリは複数値構文を使用します。

他のデータベースでは、実行されるクエリは$query->values()、トランザクションにラップされたへの呼び出しごとに1つになります。つまり、クエリの1つが失敗すると、クエリはロールバックされます。実際、InsertQuery :: execute()から実行されるコードは次のコードです。

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

つまり、挿入された値が互いに独立している場合は、使用しているコードを使用します。値が互いに依存している場合は、ここで示したコードを使用します。

あなたの場合、電子メールは互いに独立しています。私が示した2番目のスニペットを使用する場合、データベーステーブルには、サブクエリが失敗しない場合はすべての値が含まれ、単一のサブクエリが失敗する場合は何も含まれません。

drupal_write_record()他のスニペットの方がずっと好きですが、を使用することもできます。

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

ただし、このスニペットを使用しているプロはいない。

参照


1
このドキュメントページに表示されている「マルチ挿入フォーム」についてはどうですか。の配列を1つ与え、1 $valuesのみを呼び出しますexecute()drupal.org/node/310079これは、たとえば、標準プロファイルのデフォルトブロックの作成で使用されます。
テンケン

2
「本当です。->values(...)何回でも呼び出すことができ、次のInsertQueryようなクエリが準備されますINSERT INTO x (field1, field2) VALUES ('val1', 'val2'), ('val3', 'val4'), etc
Clive

2
申し訳$query->values()ありませんが、を使用して破棄した理由を思い出しました。ほとんどの場合、コードが挿入する値は互いに独立しており、ある値のエラーが他の値のロールバックを引き起こしたくないのです。
kiamlaluno

3

これはコードに似たバージョンですが、パフォーマンスは向上します。本当にexecute()を1000回呼び出したくないので、1回だけ呼び出す必要があります。

参照

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

私の場合、行数が多すぎる(10,000)とOOMエラーがスローされることを除いて、私にとってはうまくいきました。そこで、問題を解決するために、それを1000以下のバッチに分割しました。
Eduardo Chongkan
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.