2009-05-03 10 views
21

Tôi có một mảng với thông tin mà trông nhiều hơn hoặc ít hơn như thế này:Làm cách nào để thêm nhiều hàng bằng Zend_Db?

$data[] = array('content'=>'asd'); 
$data[] = array('content'=>'asdf'); 

Và tôi muốn thêm vào cả hai mục vào cơ sở dữ liệu.

$db->insert('table', $data); 

không thêm cả hai mục nhập. Tôi đang làm gì sai? Tôi có phải sử dụng Zend_ Db_Table không?

$data = array('content'=>'asdf'); 
$db->insert('table', $data); 

công trình dĩ nhiên

+3

Các đa chèn yêu cầu tính năng trong Zend 2.0 ([ZF2-475] (http://framework.zend.com/issues/browse/ZF2-475)) đã bị đóng dưới dạng wontfix. – Tgr

Trả lời

32

Tôi không nghĩ Zend_Db hỗ trợ chèn nhiều hàng.

Nhưng nếu bạn chỉ có hai hàng hoặc nhiều hơn một chút, bạn chỉ có thể sử dụng vòng lặp.

foreach ($data as $row) 
{ 
    $db->insert('table', $row) 
} 


Bill Karwin, một cựu phát triển Zend Framework, viết this on Nabble some time ago:

Rowsets cơ bản là một đối tượng thu, vì vậy tôi sẽ thêm các phương pháp để lớp đó để cho phép hàng để được thêm vào các thiết lập. Vì vậy, bạn sẽ có thể thực hiện việc này:

// creates a rowset collection with zero rows 
$rowset = $table->createRowset(); 

// creates one row with unset values 
$row = $table->createRow(); 

// adds one row to the rowset 
$rowset->addRow($row); 

// iterates over the set of rows, calling save() on each row 
$rowset->save(); 

Không có ý nghĩa gì khi chuyển một số nguyên để tạoRowset() để tạo N hàng trống. Bạn sẽ chỉ phải lặp qua chúng để điền chúng với các giá trị. Vì vậy, bạn cũng có thể viết một vòng lặp để tạo và điền các hàng riêng lẻ với dữ liệu ứng dụng, sau đó thêm chúng vào bộ sưu tập.

$rowset = $table->createRowset(); 
foreach ($appData as $tuple) 
{ 
    $row = $table->createRow($tuple); 
    $rowset->addRow($row); 
} 
$rowset->save(); 

Sẽ có ý nghĩa khi cho phép mảng mảng được chuyển đến createRowset(), vì điều này phù hợp với việc sử dụng một bộ tuple để createRow().

$rowset = $table->createRowset($appData); // pass array of tuples 

Điều này sẽ thực hiện cùng một vòng lặp như ví dụ trước ở trên (trừ lưu() ở cuối), tạo một hàng mới của hàng mới, sẵn sàng để lưu() d.

Có hai cách trong SQL để nâng cao hiệu quả chèn dữ liệu:

  1. Sử dụng một câu lệnh INSERT duy nhất với nhiều hàng:

    INSERT INTO t (col1, col2, col3) VALUES (1, 2, 3), (4, 5, 6), (7, 8, 9);

  2. Chuẩn bị một câu lệnh INSERT và thực hiện nó nhiều lần:

    CHUẨN BỊ INSERT INTO t (col1, col2, col3) GIÁ TRỊ; (,,??) EXECUTE 1, 2, 3 EXECUTE 4, 5, 6 EXECUTE 7, 8, 9

Tuy nhiên, việc hỗ trợ một trong những cải tiến này sẽ thêm phức tạp cho các lớp Row và rowSet. Điều này là do cách nội bộ lớp Zend_Db_Table_Row hiện tại phân biệt giữa một hàng cần được INSERTed hoặc UPDATEd khi bạn gọi save().Sự khác biệt này được đóng gói bởi đối tượng Row, do đó Rowset không biết các hàng riêng lẻ có là các hàng mới hay các bản sao đã sửa đổi của các hàng hiện có hay không. Do đó đối với lớp Rowset để cung cấp phương thức save() nhiều hàng sử dụng SQL hiệu quả hơn, việc quản lý dữ liệu bẩn sẽ phải được tái cấu trúc hoàn toàn. Các giải pháp dễ dàng hơn là cho Rowset để lặp qua các hàng của nó, gọi save() trên mỗi hàng. Điều này là tốt hơn cho việc đóng gói OO, mặc dù nó không giúp tối ưu hóa SQL để chèn một rowset.

Trong mọi trường hợp, rất hiếm khi tải hàng loạt dữ liệu hàng loạt trong một yêu cầu web điển hình, khi có nhu cầu lớn nhất về SQL hiệu quả. Sự khác biệt về hiệu quả cho một số lượng nhỏ các hàng nhỏ, do đó, nó sẽ là một cải tiến đáng chú ý chỉ khi bạn đang tải hàng loạt số lượng lớn hàng. Nếu đó là trường hợp, bạn không nên sử dụng INSERT anyway, bạn nên sử dụng MySQL LOAD DATA tuyên bố, hoặc tính năng tương đương nếu bạn sử dụng một thương hiệu RDBMS. INSERT thường không phải là lựa chọn hiệu quả nhất để tải nhiều dữ liệu.

Về việc trả lại tự động tạo khóa, tôi sẽ không bận tâm. Lưu ý rằng nếu bạn sử dụng SQL đơn giản (ví dụ như trong CLI mysql) và bạn chèn nhiều hàng trong một câu lệnh INSERT, bạn chỉ có thể nhận được giá trị id được tạo cuối cùng, chứ không phải giá trị id cho tất cả các hàng được chèn vào. Đây là hành vi SQL; nó là đúng cho bất kỳ ngôn ngữ hoặc khuôn khổ nào.

INSERT INTO t (col1, col2, col3) VALUES (1, 2, 3), (4, 5, 6), (7, 8, 9); 
SELECT LAST_INSERT_ID(); -- returns only the id for the third tuple 

Nếu bạn cần id cho mỗi hàng, bạn nên viết vòng lặp và chèn từng hàng một, truy xuất id được tạo sau mỗi hàng được chèn.

+0

Điều này không đúng: $ sql = "INSERT INTO beautiful (name, age) VALUES ('Helen', 24), ('Katrina', 21)"; công trình (chỉ là một ví dụ) – Thomaschaaf

+0

bạn nói đúng. Tôi vẫn không nghĩ rằng zf hỗ trợ nó và không có gợi ý cho nó bất cứ nơi nào trong hướng dẫn sử dụng. nhưng tôi không chắc chắn. – markus

+1

LOL! Tôi ước gì tôi đã có cơ hội cho upvotes cho điều đó! Làm tốt lắm Tharkun, vì đã tìm và đăng lại điều đó. –

18

Bạn có thể thực thi bất kỳ cú pháp SQL nào bạn muốn - bao gồm các câu lệnh nhiều hàng INSERT - thông qua phương thức Zend_Db_Adapter_Abstract::query().

Nhưng phương pháp của các lớp Zend_Db_TableZend_Db_Table_Rowset không có hỗ trợ cho việc chèn nhiều hàng trong một lần.

+3

corect. nhưng insertMultiple() sẽ hữu ích và dễ dàng hơn nhiều ... –

+0

@Elzo Valugi, không có phương thức 'insertMultiple()' nào trong hướng dẫn và trong khung – Green

+1

"là" hiện diện, "sẽ" là một (có thể/có thể xảy ra) trong tương lai. có lẽ tôi nên sử dụng "sẽ". Chỉ cần làm rõ :) –

10

để chèn nhiều hàng bạn có thể sử dụng Zend_Db

$stmt = $table->getAdapter()->prepare('INSERT INTO tablename (col1, col2, col3) VALUES (?, ?, ?), (?, ?, ?)'); 

$stmt->execute(array($value1, $value2, $value3, $value4, $value5, $value6)); 

(từ Bill Karwin)

trong trường hợp của bạn, chúng tôi có thể thay đổi điều đó để mã này:

$data[] = array('content'=>'asd'); 
$data[] = array('content'=>'asdf'); 

$stmt = $table->getAdapter()->prepare('INSERT INTO table (col1) VALUES (?), (?)'); 
$stmt->execute($data); 

để tạo ra những ' (?), (?) 'động, khi dữ liệu động, bạn có thể thử sử dụng đoạn mã này:

$values = implode(',',array_fill(0,count($data),'(?)')); 

hy vọng điều này giúp

regards, Riki Risnandar

+2

Tôi không nghĩ rằng điều này hoạt động? Tôi có $ list = array(); $ list [] = mảng (': x' => 1, ': y' => 1); $ stmt = $ this-> table-> getAdapter() -> chuẩn bị ('INSERT INTO ở đây (x, y) GIÁ TRỊ (: x,: y), (: x,: y)'); $ stmt-> execute ($ list); và nó nói: 'Số tham số không hợp lệ: số biến bị ràng buộc không khớp với số mã thông báo'. Nếu tôi không sử dụng một mảng MD thì ok của nó ... Tôi không nghĩ rằng thực hiện là nghĩa vụ phải mất một mảng MD? –

+0

tính năng này không có tác dụng đối với tôi, tôi nhận được lỗi có quá nhiều phần giữ chỗ. Đang cố gắng chèn 50.000 hàng. – Ray

1

Nếu bạn sử dụng ZF2 sau đó giải pháp có thể là như thế này:

$insert = $this->getSql()->insert(); 
foreach ($values as $value) { 
    $relation = array(
     'column_one' => $value, 
     'column_two' => $value 
    ); 
    $insert->values($relation, Insert::VALUES_MERGE); 
} 

$insertRes = $this->executeInsert($insert); 
1

Đó là công việc.

$query = 'INSERT INTO ' . $db->quoteIdentifier('table') . ' (`col1`, `col2`) VALUES '; 
    $queryVals = array(); 
    foreach ($data as $row) { 
     foreach($row as &$col) { 
      $col = $db->quote($col); 
     } 
     $queryVals[] = '(' . implode(',', $row) . ')'; 
    } 
    $stmt = $db->query($query . implode(',', $queryVals)); 

how to build multiple insert query in zend framework

2

đây là giải pháp của tôi:

public function saveRows($array) { 
     $vAmount = count($array); 
     $values  = array(); 
     $columns = array(); 

     foreach ($array as $colval) { 
      foreach ($colval as $column=>$value) { 
       array_push($values,$value); 
       !in_array($column,$columns) ? array_push($columns,$column) : null; 
      } 
     } 

     $cAmount = count($columns); 
     $values  = array_chunk($values, $cAmount); 
     $iValues = ''; 
     $iColumns = implode("`, `", $columns); 

     for($i=0; $i<$vAmount;$i++) 
      $iValues.="('".implode("', '", $values[$i])."')".(($i+1)!=$vAmount ? ',' : null); 

     $data="INSERT INTO `".$this->_name."` (`".$iColumns."`) VALUES ".$iValues; 
     die($data); 
     $this->query($data); 
    } 
+1

Bạn thực sự nên thoát khỏi các tham số truy vấn của mình. – Eric