2010-04-14 27 views
23

Tôi đã tìm thấy một vài câu trả lời cho điều này bằng cách sử dụng mySQL, nhưng tôi hy vọng ai đó có thể chỉ cho tôi một cách để lấy ID của hàng được chèn hoặc cập nhật cuối cùng một mysql DB khi sử dụng PHP để xử lý các chèn/cập nhật.nhận mysql_insert_id() trong khi sử dụng ON DUPLICATE KEY UPDATE với PHP

Hiện nay tôi có một cái gì đó như thế này, nơi cột3 là một khóa duy nhất, và đó cũng là một cột id đó là một khóa chính autoincremented:

$query ="INSERT INTO TABLE (column1, column2, column3) VALUES (value1, value2, value3) ON DUPLICATE KEY UPDATE SET column1=value1, column2=value2, column3=value3"; 
mysql_query($query); 

$my_id = mysql_insert_id(); 

$ my_id là đúng trên INSERT, nhưng không chính xác khi nó cập nhật một hàng (ON CẬP NHẬT KEY DUPLICATE).

Tôi đã thấy nhiều bài viết với những người tư vấn mà bạn sử dụng một cái gì đó giống như

INSERT INTO table (a) VALUES (0) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id) 

để có được một giá trị ID hợp lệ khi ON DUPLICATE KEY là invoked-- nhưng sẽ trở lại này mà ID hợp lệ để PHP mysql_insert_id() chức năng?

+0

Tôi không có câu trả lời. Nhưng giải pháp trông rất thông minh. Tại sao bạn không thử nó? Tôi nghĩ sẽ không khó để tạo ra một trường hợp thử nghiệm mà sẽ đưa ra một câu trả lời dứt khoát. PS: Đừng hiểu lầm tôi; Tôi có thể hiểu bạn sẽ muốn đảm bảo. Có lẽ tôi cũng vậy. Nhưng tôi sẽ thử nó trước tiên. :) –

+2

Tôi đã tò mò làm thế nào mà có thể làm việc nhưng tôi tìm thấy điều này trong hướng dẫn MySQL: * Nếu expr được đưa ra như là một đối số để LAST_INSERT_ID(), giá trị của đối số được trả về bởi hàm và được nhớ là giá trị tiếp theo được trả về bởi LAST_INSERT_ID() *. –

+0

@Alexandre: có, và giả sử 'mysql_insert_id()' chỉ là một proxy cho 'LAST \ _INSERT \ _ID()' Tôi nghĩ rằng điều này sẽ làm việc như mong đợi. –

Trả lời

34

Dưới đây là câu trả lời, theo đề nghị của Alexandre:

khi bạn sử dụng id = LAST_INSERT_ID (id) nó đặt giá trị của mysql_insert_id = các ID-- cập nhật để mã cuối cùng của bạn sẽ giống như thế:

<? 
    $query = mysql_query(" 
     INSERT INTO table (column1, column2, column3) 
     VALUES (value1, value2, value3) 
     ON DUPLICATE KEY UPDATE 
      column1 = value1, 
      column2 = value2, 
      column3 = value3, 
      id=LAST_INSERT_ID(id) 
    "); 
    $my_id = mysql_insert_id(); 

này sẽ trả về giá trị đúng với $ my_id bất kể update o r chèn.

+0

nếu id đang được cập nhật đang được tham chiếu trong một bảng khác thì sao? điều này có gây rắc rối không? – ianace

+5

Điều này đã giúp tôi, nhưng chỉ để được rõ ràng, cho bất cứ ai khác có vấn đề ... Nếu hồ sơ đã tồn tại và được cập nhật, cuộc gọi đến LAST_INSERT_ID() đảm bảo rằng khi bạn gọi mysql_insert_id(), nó sẽ trả về id của bản ghi được cập nhật và không bằng 0 như thường lệ. Cũng lưu ý rằng "id" nên được thay thế bằng tên cột auto_increment trong bảng. Thông tin thêm: http://dev.mysql.com/doc/refman/5.1/en/insert-on-duplicate.html –

10

Bạn có thể kiểm tra xem truy vấn là một chèn hoặc cập nhật (mysql_affected_rows(); trả về 1 khi chèn và 2 khi cập nhật).

Nếu đó là chèn sử dụng mysql_insert_id, nếu đó là bản cập nhật bạn cần một Truy vấn khác.

<?php 
$query ="INSERT INTO TABLE (column1, column2, column3) VALUES (value1, value2, value3) ON DUPLICATE KEY UPDATE SET column1=value1, column2=value2, column3=value3"; 
mysql_query($query); 
if(mysql_affected_rows() == 1) { $id = mysql_insert_id(); } 
else { // select ... 
} 
?> 

Tôi biết nó không phải là excatly những gì bạn đang tìm kiếm nhưng đó là tốt nhất tôi có thể đưa ra

+1

+1 cho affected_rows() trả về 1 khi chèn và 2 để cập nhật. –

+3

nếu không có gì được cập nhật (các giá trị giống như trong db), cũng không được chèn vào; hàng bị ảnh hưởng trả về 0 –

1

Mặc dù không sử dụng mysql_insert_id() và ON DUPLICATE CẬP NHẬT KEY, cách tuyệt vời thay thế để có được giá trị của trường nào khi cập nhật khác tìm thấy here:

UPDATE table SET id=(@tempid:=id) , .... LIMIT 1; 
SELECT @tempid; 

tôi đã sử dụng nó có bảng với (id, tình trạng) 'id' tự động tăng chỉ mục chính và 'trạng thái' là trường mà cập nhật được tạo, nhưng tôi cần có 'id' của hàng được cập nhật. Giải pháp này cũng chứng minh điều kiện chủng tộc như mysql_insert_id().

0

Đây là giải pháp của tôi nơi bạn đặt dữ liệu vào một mảng duy nhất và nó tự động được nhân bản/được điền vào truy vấn "INSERT INTO .. ​​ON DUPLICATE UPDATE ..".

Thật tuyệt vời để bảo trì và nếu bạn muốn bạn cũng có thể làm cho nó trở thành một hàm/phương pháp.

// save to db: 

$qData = [ 
    "id" =>    mysql_real_escape_string($email_id),  
    "synd_id" =>   mysql_real_escape_string($synd_id), 
    "campaign_id" =>  mysql_real_escape_string($campaign_id), 
    "event_id" =>   mysql_real_escape_string($event_id), 
    "user_id" =>   mysql_real_escape_string($user_id), 
    "campaign_name" =>  mysql_real_escape_string($campaign_name), 
    "subject" =>   mysql_real_escape_string($subject), 
    "from_name"=>   mysql_real_escape_string($from_name), 
    "from_email"=>   mysql_real_escape_string($from), 
    "content"=>   mysql_real_escape_string($html), 
    "link_to_template" => mysql_real_escape_string($hash), 
    "ext_campaign_id" => mysql_real_escape_string($ext_campaign_id), 
    "ext_list_id"=>  mysql_real_escape_string($ext_list_id), 
]; 


$q = "INSERT INTO email_campaigns (". 
    // i.e create a string like `id`, `synd_id`, `campaign_id`.. with linebreaks for readability 
    implode(", \n", array_map(function($k){ return "`$k`"; }, array_keys($qData))) 
.") 
VALUES (". 
    // i.e '20', '532', '600' .. 
    implode(", \n", array_map(function($v){ return "'$v'"; }, array_values($qData))) 
.") ON DUPLICATE KEY UPDATE ". 
    // i.e `synd_id`='532', `campaign_id`='600' ... 
    // id & link_to_template table keys are excluded based on the array below 
    implode(", \n", array_filter(array_map(function($k, $v){ if(!in_array($k, ['id', 'link_to_template'])) return "`$k`='$v'" ; }, array_keys($qData), array_values($qData)))) ; 
Các vấn đề liên quan