Làm cách nào để lưu mảng giá trị trong cơ sở dữ liệu?


8

Tôi đang cố gắng lưu nhiều giá trị từ một vùng văn bản vào bảng cơ sở dữ liệu.

Tôi sử dụng mã sau đây, nhưng tôi cảm thấy đó là cách sai.

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

Có một cách khác nhau để đạt được kết quả tương tự?

Câu trả lời:


15

Tôi sẽ sử dụng mã sau đây.

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

Ngoài ra, bạn có thể sử dụng mã sau đây.

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

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

$query->execute();

Với MySQL, truy vấn sử dụng cú pháp đa giá trị.

Với các cơ sở dữ liệu khác, các truy vấn được thực hiện sẽ là một cho mỗi cuộc gọi đến $query->values(), được gói trong một giao dịch. Điều này có nghĩa là các truy vấn sẽ được khôi phục khi một trong số chúng thất bại. Trong thực tế, mã được thực thi từ insertQuery :: exec () là mã sau đây.

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

Nói tóm lại, tôi sẽ sử dụng mã bạn đang sử dụng nếu các giá trị được chèn độc lập với nhau; Tôi sẽ sử dụng mã tôi đã hiển thị khi các giá trị phụ thuộc lẫn nhau.

Trong trường hợp của bạn, các email là độc lập với nhau. Nếu bạn sẽ sử dụng đoạn mã thứ hai mà tôi đã hiển thị, bảng cơ sở dữ liệu sẽ chứa tất cả các giá trị, khi truy vấn phụ không bị lỗi hoặc không có gì khi một truy vấn phụ không thành công.

Bạn cũng có thể sử dụng drupal_write_record(), mặc dù tôi rất thích các đoạn khác.

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

Mặc dù vậy, tôi không thấy bất kỳ chuyên gia nào trong việc sử dụng đoạn trích này.

Tài liệu tham khảo


1
Tôi xin lỗi những gì về "Biểu mẫu đa chèn" được hiển thị trên trang tài liệu này. Cho 1 mảng $valuesvà chỉ gọi 1 execute(). drupal.org/node/310079 Ví dụ này được sử dụng trong việc tạo khối mặc định của cấu hình tiêu chuẩn.
tenken

2
'Đây là sự thật, bạn có thể gọi ->values(...)bao nhiêu lần tùy ý InsertQueryvà nó sẽ chuẩn bị một truy vấn nhưINSERT INTO x (field1, field2) VALUES ('val1', 'val2'), ('val3', 'val4'), etc
Clive

2
Được rồi, bây giờ tôi đã nhớ tại sao tôi loại bỏ bằng cách sử dụng $query->values(): Trong hầu hết các trường hợp của tôi, các giá trị mà mã mà tôi đang chèn là độc lập với nhau và tôi không muốn rằng lỗi có giá trị gây ra sự đảo ngược của các giá trị khác.
kiamlaluno

3

Đây là một phiên bản tương tự như mã của bạn, nhưng hiệu suất tốt hơn. Bạn thực sự không muốn gọi exec () một ngàn lần, bạn chỉ cần gọi nó một lần.

Tài liệu tham khảo

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

Làm việc cho tôi ngoại trừ việc nó sẽ ném lỗi OOM khi số lượng dòng quá lớn (10.000) trong trường hợp của tôi. Vì vậy, tôi chia nó thành các đợt 1000 hoặc ít hơn để giải quyết vấn đề đó.
Eduardo Chongkan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.