Tôi không nghĩ rằng 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 một vòng lặp.
foreach ($data as $row)
{
$db->insert('table', $row)
}
Bill Karwin , một cựu nhà phát triển Zend Framework, đã viết cái này trên Nabble một thời gian trước :
Rowsets về cơ bản là một đối tượng tập hợp, vì vậy tôi sẽ thêm các phương thức vào lớp đó để cho phép các hàng được thêm vào tập hợp. Vì vậy, bạn sẽ có thể làm điều 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 truyền một số nguyên vào createRowset () để tạo N hàng trống. Bạn sẽ chỉ phải lặp lại chúng để điền vào chúng 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();
Việc cho phép một dãy mảng được truyền vào createRowset () cũng rất hợp lý, vì điều này sẽ phù hợp với việc sử dụng truyền một tuple tới createRow ().
$rowset = $table->createRowset($appData); // pass array of tuples
Điều này sẽ thực hiện vòng lặp tương tự như ví dụ trước ở trên (ngoại trừ lưu () ở cuối), tạo một tập hợp các hàng mới, sẵn sàng để được lưu () d.
Có hai cách trong SQL để cải thiện hiệu quả của việc chèn dữ liệu:
-
Sử dụng một câu lệnh INSERT với nhiều hàng:
CHÈN VÀO T (col1, col2, col3) CÁC GIÁ TRỊ (1, 2, 3), (4, 5, 6), (7, 8, 9);
-
Chuẩn bị một câu lệnh INSERT và thực thi nó nhiều lần:
CHUẨN BỊ CHÈN VÀO CÁC GIÁ TRỊ (?
Tuy nhiên, việc hỗ trợ một trong hai cải tiến này sẽ làm tăng thêm độ phức tạp cho các lớp Row và Rowset. Điều này là do cách bên trong lớp Zend_Db_Table_Row hiện tại phân biệt giữa một hàng cần được CHÈN hoặc CẬP NHẬT khi bạn gọi lưu (). Sự khác biệt này được đóng gói bởi đối tượng Row, vì vậy Rowset không biết liệu các hàng riêng lẻ là hàng mới hay bản sao sửa đổi của các hàng hiện có. Do đó, để lớp Rowset cung cấp phương thức lưu () 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 cấu trúc lại hoàn toàn. Giải pháp dễ dàng hơn là Rowset lặp qua các hàng của nó, gọi save () trên mỗi hàng. Điều này 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 tập hợp hàng.
Trong mọi trường hợp, thực sự hiếm khi tải hàng loạt nhiều hàng dữ liệu trong một yêu cầu web điển hình, khi nhu cầu lớn nhất về SQL hiệu quả. Sự khác biệt về hiệu quả đối với một số lượng nhỏ hàng là nhỏ, vì vậy nó sẽ là một cải tiến đáng chú ý chỉ nếu bạn đang tải hàng loạt một số lượng lớn hàng. Nếu đúng như vậy, bạn vẫn không nên sử dụng INSERT, bạn nên sử dụng câu lệnh LOAD DATA của MySQL hoặc tính năng tương đương nếu bạn sử dụng thương hiệu RDBMS khác. 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 các khóa được tạo tự động, tôi sẽ không bận tâm. Lưu ý rằng nếu bạn sử dụng SQL thuần túy (trong mysql CLI chẳng hạn) 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, không phải giá trị id cho tất cả các hàng được chèn. Đây là hành vi SQL; nó đúng cho bất kỳ ngôn ngữ hoặc bất kỳ 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 một vòng lặp và chèn từng hàng một, truy xuất id đã tạo sau mỗi hàng được chèn.