2011-09-07 41 views
44

Thông thường tôi có thể chèn một hàng vào bảng MySQL và lấy lại last_insert_id. Bây giờ, mặc dù, tôi muốn chèn số lượng lớn nhiều hàng vào bảng và lấy lại một mảng các ID. Có ai biết làm thế nào tôi có thể làm điều này?Làm cách nào để chèn nhiều hàng vào bảng MySQL và trả về các ID mới?

Có một số câu hỏi tương tự, nhưng chúng không giống hệt nhau. Tôi không muốn chèn ID mới vào bất kỳ bảng tạm thời nào; Tôi chỉ muốn lấy lại mảng ID.

Can I retrieve the lastInsertId from a bulk insert?

Mysql mulitple row insert-select statement with last_insert_id()

+0

Tại sao bạn không thể chèn từng cái một? – sanmai

+0

Bạn cần mô phỏng mệnh đề 'OUTPUT'. Tôi tin rằng bạn có thể làm điều này với một kích hoạt trong MySQL –

+0

Bạn không thể sử dụng chèn số lượng lớn và sau đó một hàm lime last_insert_id(), nó không hoạt động. –

Trả lời

41

Chủ đề cũ nhưng chỉ xem xét vấn đề này, vì vậy ở đây: nếu bạn đang sử dụng InnoDB trên phiên bản MySQL gần đây, bạn có thể lấy danh sách ID bằng LAST_INSERT_ID() và ROW_COUNT().

InnoDB đảm bảo các số liên tiếp cho AUTO INCREMENT khi chèn số lượng lớn, cung cấp innodb_autoinc_lock_mode được đặt thành 0 (truyền thống) hoặc 1 (liên tiếp). Do đó, bạn có thể nhận được ID đầu tiên từ LAST_INSERT_ID() và lần cuối bằng cách thêm ROW_COUNT() - 1.

+2

Bạn có cần giao dịch không? Điều gì sẽ xảy ra nếu chèn khác ở giữa? – Mark

+3

Miễn là bạn sử dụng động cơ InnoDB và đảm bảo rằng khóa auto_increment được bật (có thể dẫn đến hiệu năng chậm hơn), không cần định nghĩa giao dịch rõ ràng. Do InnoDB thực hiện khóa trong khi chèn, các chèn khác phải đợi cho quá trình chèn hoàn tất. Hãy xem http://dev.mysql.com/doc/refman/5.1/en/innodb-auto-increment-handling.html –

+0

Còn MYISAM thì sao? – CMCDragonkai

9

Cách duy nhất tôi có thể nghĩ rằng nó có thể được thực hiện là nếu bạn lưu trữ một định danh duy nhất cho mỗi tập hợp các hàng chèn (GUID) sau đó chọn id hàng. ví dụ:

INSERT INTO t1 
(SELECT col1,col2,col3,'3aee88e2-a981-1027-a396-84f02afe7c70' FROM a_very_large_table); 
COMMIT; 

SELECT id FROM t1 
WHERE guid='3aee88e2-a981-1027-a396-84f02afe7c70'; 

Bạn cũng có thể tạo ra các guid trong cơ sở dữ liệu bằng cách sử dụng uuid()

-8
$query = "INSERT INTO TABLE (ID,NAME,EMAIL) VALUES (NULL,VALUE1, VALUE2)"; 
$idArray = array(); 
foreach($array as $key) { 
mysql_query($query); 
array_push($idArray, mysql_insert_id()); 
} 
print_r($idArray); 
+2

nó không phải là một truy vấn chèn số lượng lớn. – Peacemoon

0

Tôi nghĩ rằng bạn sẽ phải hoặc là xử lý các id giao dịch trong ứng dụng của bạn, hoặc id mục trong bạn ứng dụng để làm điều này hoàn hảo. (!)

Một cách để làm điều này mà có thể làm việc, giả định rằng tất cả chèn của bạn thành công, như sau:

Bạn có thể sau đó nhận của chèn id với một vòng lặp cho số hàng bị ảnh hưởng, bắt đầu với lastid (là id được chèn đầu tiên của chèn số lượng lớn). Và do đó, tôi đã kiểm tra nó hoạt động hoàn hảo .. chỉ cần cẩn thận rằng HeidiSQL chẳng hạn sẽ trả về giá trị đúng cho ROW_COUNT(), có lẽ bởi vì nó là một giao diện crappy làm việc ngẫu nhiên, chúng tôi không hỏi nó - tuy nhiên nó hoàn toàn chính xác một trong hai dòng lệnh hoặc PHP mysqli -

START TRANSACTION; 
BEGIN; 
INSERT into test (b) VALUES ('1'),('2'),('3'); 
SELECT LAST_INSERT_ID() AS lastid,ROW_COUNT() AS rowcount; 
COMMIT; 

Trong PHP nó trông như thế này (local_sqle là lời kêu gọi thẳng đến mysqli_query, local_sqlec là một lời kêu gọi mysqli_query + chuyển đổi resultset để PHP mảng):

local_sqle("START TRANSACTION; 
BEGIN; 
INSERT into test (b) VALUES ('1'),('2'),('3');"); 
$r=local_sqlec("SELECT LAST_INSERT_ID() AS lastid,ROW_COUNT() AS rowcount;"); 
local_sqle(" 
COMMIT;"); 
$i=0; 
echo "last id =".($r[0]['lastid'])."<br>"; 
echo "Row count =".($r[0]['rowcount'])."<br>"; 

while($i<$r[0]['rowcount']){ 
    echo "inserted id =".($r[0]['lastid']+$i)."<br>"; 
    $i++; 
} 

Lý do các truy vấn được tách ra là bởi vì tôi sẽ không nhận được kết quả của tôi bằng cách sử dụng các chức năng của riêng tôi, nếu yo u làm điều này với các hàm chuẩn, bạn có thể đặt nó trở lại trong một câu lệnh và sau đó lấy kết quả bạn cần (nó sẽ là kết quả số 2 - giả sử bạn sử dụng phần mở rộng xử lý nhiều hơn một tập kết quả/truy vấn).

1

Giả sử chúng tôi có một bảng được gọi là hấp dẫn với hai cid uid, col1 trong đó uid là trường tăng tự động. Làm một cái gì đó như dưới đây sẽ trả về tất cả các id được chèn vào trong resultset. Bạn có thể lặp qua resultset và lấy id của bạn. Tôi nhận ra rằng đây là một bài đăng cũ và giải pháp này có thể không hoạt động cho mọi trường hợp. Nhưng đối với những người khác nó có thể và đó là lý do tại sao tôi đang trả lời nó.

# lock the table 
lock tables temptable write; 

#bulk insert the rows; 
insert into temptable(col1) values(1),(2),(3),(4); 

#get the value of first inserted row. when bulk inserting last_insert_id() #should give the value of first inserted row from bulk op. 
set @first_id = last_insert_id(); 

#now select the auto increment field whose value is greater than equal to #the first row. Remember since you have write lock on that table other #sessions can't write to it. This resultset should have all the inserted #id's 
select uid from temptable where uid >[email protected]_id; 

#now that you are done don't forget to unlock the table. 
unlock tables; 
Các vấn đề liên quan