使用自動遞增欄位本身並沒有錯。使用其主要競爭方案,也就是由資料庫提供一組非重複的識別碼(通常是整數)也沒有錯。這就好比你開車要靠哪邊行駛一樣。
更大的問題是人們不了解他們在進行資料庫存取時的操作。這就像在不真正了解交通規則的情況下開車。這樣的人會在不知不覺中做出錯誤的決定,最終導致某些問題發生。
資料庫是複雜的,值得花時間去真正理解。學習不同解決問題方法的含義和限制。這樣,您就能夠根據實際情況選擇合適的解決方案。
(PHP 4, PHP 5)
mysql_insert_id — 取得上一個查詢產生的 ID
此擴充套件已於 PHP 5.5.0 中棄用,並已於 PHP 7.0.0 中移除。建議改用 MySQLi 或 PDO_MySQL 擴充套件。另請參閱 MySQL:選擇 API 指南。此函式的替代方案包括:
link_identifier
MySQL 連線。如果未指定連結識別碼,則假設為 mysql_connect() 開啟的最後一個連結。如果找不到此類連結,它會嘗試建立一個連結,如同以無參數呼叫 mysql_connect() 一樣。如果找不到或建立連線,則會產生 E_WARNING
等級的錯誤。
成功時,返回前一個查詢為 AUTO_INCREMENT 欄位產生的 ID;如果前一個查詢未產生 AUTO_INCREMENT 值,則返回 0
;如果未建立 MySQL 連線,則返回 false
。
範例 #1 mysql_insert_id() 範例
<?php
$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
if (!$link) {
die('無法連線: ' . mysql_error());
}
mysql_select_db('mydb');
mysql_query("INSERT INTO mytable (product) values ('kossu')");
printf("最後插入的記錄 ID 為 %d\n", mysql_insert_id());
?>
mysql_insert_id() 會將原生 MySQL C API 函式 mysql_insert_id()
的返回類型轉換為 long
類型(在 PHP 中稱為 int)。如果您的 AUTO_INCREMENT 欄位的欄位類型為 BIGINT(64 位元),則轉換可能會導致值不正確。此時,請在 SQL 查詢中使用內部 MySQL SQL 函式 LAST_INSERT_ID()。有關 PHP 最大整數值的更多資訊,請參閱 整數 文件。
備註:
因為 mysql_insert_id() 作用於最後執行的查詢,所以請務必在產生值的查詢之後立即呼叫 mysql_insert_id()。
備註:
MySQL SQL 函式
LAST_INSERT_ID()
的值始終包含最近產生的 AUTO_INCREMENT 值,並且在查詢之間不會重置。
使用自動遞增欄位本身並沒有錯。使用其主要競爭方案,也就是由資料庫提供一組非重複的識別碼(通常是整數)也沒有錯。這就好比你開車要靠哪邊行駛一樣。
更大的問題是人們不了解他們在進行資料庫存取時的操作。這就像在不真正了解交通規則的情況下開車。這樣的人會在不知不覺中做出錯誤的決定,最終導致某些問題發生。
資料庫是複雜的,值得花時間去真正理解。學習不同解決問題方法的含義和限制。這樣,您就能夠根據實際情況選擇合適的解決方案。
不要使用 MAX 來獲取最後插入的 ID。競爭條件,例如其他使用者在您的 SELECT MAX(.. 和 INSERT 之間插入數據,可能會導致您的 ID 無法使用。
獲取 ID 的正確方法是使用 mysql_insert_id() 或 MySQL SQL 函數 LAST_INSERT_ID()。
請注意,如果使用 mysql_insert_id(),您應該提供 mysql_connect 返回的資源,而不是 mysql_query 返回的結果集。
我不太明白這有什麼好大驚小怪的。
我讀到
「mysql_insert_id() 的值僅受當前客戶端連線中發出的語句影響。它不受其他客戶端發出的語句影響。」
參見:https://mysqldev.dev.org.tw/doc/refman/5.0/es/mysql-insert-id.html
我真的看不出這有什麼不準確之處。
「如果是多行 INSERT 語句,mysql_insert_id() 會返回第一個自動生成的 AUTO_INCREMENT 值;如果沒有生成這樣的值,它會返回最後插入到 AUTO_INCREMENT 欄位中的顯式值。」
我一定是遺漏了什麼,但為什麼要插入多行,然後只用一些偏好的行為處理最後一行呢?您也可以一次插入一行,然後使用最新的 ID 分別處理每一行。
我看不出這有什麼問題。
然而,我可以看到僅使用 max(my_table.id_column) 的問題所在,因為這會導致併發存取的問題。
我認為這與所有使用 mysqli 並在 INSERT 命令後尋找 ID 的人有關
<?php
function insert_join($catid, $disc_id) {
// 插入新的項目到資料庫
$conn = db_connect();
// 插入新項目
$demande = "insert into categories_disc values ('', '".$catid."', '".$disc_id."')";
$resultat = $conn->query($demande);
if (!$resultat) {
return false;
} else {
return $conn->insert_id; // 這個函式現在會回傳 ID 而不是 true。
}
}
?>
接著,在另一端,我們可以這樣呼叫這個函式:
<?php
$cat_id = insert_join($catid, $disc_id);
if($cat_id !== false) {
echo "<p>類別資料已新增至資料庫,如下所示:<br>";
echo "<hr>類別 ID:".$cat_id."</p><hr>";
}
?>
如何在 MySQL 中取得最後更新列的 ID?
75
down vote
我找到這個問題的答案了 :)
by Pomyk
SET @update_id := 0;
UPDATE some_table SET row = 'value', id = (SELECT @update_id := id)
WHERE some_other_row = 'blah' LIMIT 1;
SELECT @update_id;
由 aefxx 編輯
這個技巧可以進一步擴展,以取得受 update 陳述式影響的每一列的 ID
SET @uids := null;
UPDATE footable
SET foo = 'bar'
WHERE fooid > 5
AND ( SELECT @uids := CONCAT_WS(',', fooid, @uids) );
SELECT @uids;
這會回傳一個字串,其中包含所有以冒號串連的 ID。
(問題來源:stackoverflow,編號 1388025)
如果您使用 INSERT 陳述式中的 ON DUPLICATE KEY UPDATE 子句插入資料列,mysql_insert_id() 函式回傳的結果將與您直接在 MySQL 中使用 LAST_INSERT_ID() 的結果不同。
請參考以下範例
<?
// 插入一筆資料列,主鍵為 auto_increment
// value 是一個唯一鍵值
$query = "INSERT INTO test (value) VALUES ('test')";
mysql_query( $query );
echo 'LAST_INSERT_ID: ',
mysql_query( "SELECT LAST_INSERT_ID()" ),
'<br>mysql_insert_id: ',
mysql_insert_id();
?>
這會印出
LAST_INSERT_ID: 1
mysql_insert_id: 1
在這種情況下,函式的返回值與 MySQL 陳述式相同。
但請參考在現有鍵值上插入的情況
<?
$query = "INSERT INTO test (value)
VALUES ('test')
ON DUPLICATE KEY UPDATE value = 'test2'";
mysql_query( $query );
echo 'LAST_INSERT_ID: ',
mysql_query( "SELECT LAST_INSERT_ID()" ),
'<br>mysql_insert_id: ',
mysql_insert_id();
?>
這會印出
LAST_INSERT_ID: 2
mysql_insert_id: 1
使用 ON DUPLICATE KEY UPDATE 子句時,如果 INSERT 陳述式造成重複的項目,則只會修改舊的資料列,但 LAST_INSERT_ID() 函式會傳回主鍵的下一個自動遞增值,順帶一提,這個值並不會被設定為資料庫中的下一個自動遞增值。
mysql_insert_id() 函式會傳回舊的(已更改的)資料列的主鍵。對我來說,這是正確的操作方法,因為 LAST_INSERT_ID() 函式傳回的值根本沒有參考任何資料列。
來自慕尼黑的問候。
heiligkind
如果 mysql_insert_id() 傳回 0 或 null,請檢查您的自動遞增欄位是否沒有被您的 SQL 查詢設定,如果您像我一樣有多個資料庫連線,解決方案是為此查詢建立一個獨立的資料庫連線。
您不能執行 INSERT DELAYED 並期望獲得非零的值,因為它是在一個獨立的執行緒中執行的,而 mysql_insert_id() 是與目前的執行緒綁定的。
Vlad
MySQLi 程序式
//---------------------------------------------
$last_id = mysqli_insert_id($conn);
//---------------------------------------------
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";
// 建立連線
$conn = mysqli_connect($servername, $username, $password, $dbname);
// 檢查連線
if (!$conn) {
die("連線失敗: " . mysqli_connect_error());
}
$sql = "INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('John', 'Doe', 'john@example.com')";
if (mysqli_query($conn, $sql)) {
$last_id = mysqli_insert_id($conn);
echo "新增記錄成功。最後插入的 ID 為: " . $last_id;
} else {
echo "錯誤: " . $sql . "<br>" . mysqli_error($conn);
}
mysqli_close($conn);
?>