2012-02-01 29 views
6

Có cách nào để lấy ID của bản ghi (khóa chính) sau khi chèn khi lỗi mysql trả về một khóa trùng lặp không?Nhận ID hồ sơ khi mysql trả về lỗi trùng lặp

E.G. Làm thế nào tôi sẽ đi về nó:

$sql = "INSERT INTO table (`col1`, `col2`) VALUES ('$val1', '$val2')"; 
$result = mysql_query($sql); 
if($result){ 
    $id = mysql_insert_id(); 
} 
else { 
    if(stristr(mysql_error(), "duplicate"){ 
    $sql = "SELECT `id` FROM `table` WHERE `col1`='$val1' AND `col2`='$val2'"; 
    $result = mysql_query($sql); 
    $row = mysql_fetch_array($result); 
    $id = $row['id']; 
    } 
    else { 
    die(mysql_error()); 
    } 
} 

Ở đây tôi phải thực hiện hai câu lệnh sql không chỉ mất thời gian và công sức mà còn cả mã trùng lặp nữa.

Tôi không thể sử dụng ON DUPLICATE KEY UPDATE vì tôi muốn cập nhật một bảng khác bằng cách sử dụng id được chèn cuối cùng hoặc id của bản ghi không thể sao chép được.

Vì vậy, tôi có làm đúng những gì tôi đang làm không? Hoặc là có một cách để có được id của hàng?

Cảm ơn

Trả lời

6

MySQL sẽ không cho bạn biết kỷ lục giữ giá trị ban đầu, bạn sẽ phải tìm ra cho mình. Dưới đây là một số mẹo:

  • Tìm chuỗi duplicate trong văn bản của thông báo lỗi trông không thật mạnh mẽ. Bạn chỉ có thể kiểm tra giá trị của mysql_errno() đối với mã cho mục trùng lặp, là 1062 (you can find all codes in the manual).
  • Việc gia hạn mysql không cung cấp một cơ chế để tìm ra tên của khóa vi phạm, vì vậy bạn sẽ phải sử dụng phương pháp tiếp cận phi mạnh mẽ của phân tích nội dung của thông báo lỗi:

    if(preg_match("/Duplicate entry '.*' for key '(.*)'/Ui", mysql_error(), $matches)){ 
        $violated_key = $matches[1]; 
    }else{ 
        throw new Exception('Could not find violated key name'); 
    } 
    
  • Ngoài ra, chỉ cần chạy một truy vấn trước đó (không có lý do để tránh nó):

    SELECT id 
    FROM table 
    WHERE col1=... AND col2=... 
    FOR UPDATE 
    

    mệnh FOR UPDATE sẽ khóa hàng phù hợp để tránh điều kiện chủng tộc (giả sử InnoDB).

+0

Tuyệt vời, cảm ơn thông tin và mẹo. –

+0

Rất vui được. Hãy để tôi thêm một lưu ý: rõ ràng, 'FOR UPDATE' sẽ khóa không có gì nếu không có kết quả phù hợp. Bạn vẫn có thể nhận được bản ghi được tạo bởi quá trình đồng thời khác ngay sau khi kiểm tra. Chỉ cần tính đến điều đó. –

+0

Ok, cảm ơn. Tôi không sử dụng InnoDB, và không bao giờ có, vì vậy tôi không chắc chắn những gì bạn đang nói về! : p Nhưng tôi sẽ xem xét nó. :) –

Các vấn đề liên quan