萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL INSERT 後獲取自增 ID:mysql_insert_id()、LAST_INSERT_ID() 與連線池陷阱

插入資料後立即取得自增主鍵值,是常見需求。MySQL 提供函數與 SQL 函數兩種方式,需注意連線池環境下的正確用法。

PHP mysql_insert_id()(舊擴展,已棄用)


$link = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('mydb');
mysql_query("INSERT INTO `t` (`name`) VALUES ('test')");
$id = mysql_insert_id($link); // 返回最後一次 INSERT 的 AUTO_INCREMENT 值
printf("Last ID: %d", $id);

警告:mysql_* 函數 PHP 5.5 棄用,PHP 7.0 移除。請改用 mysqli 或 PDO。

mysqli / PDO 正確用法

mysqli 物件導向


$mysqli = new mysqli('localhost', 'user', 'pass', 'mydb');
$mysqli->query("INSERT INTO `t` (`name`) VALUES ('test')");
$id = $mysqli->insert_id; // 屬性
// 或
$id = $mysqli->query("SELECT LAST_INSERT_ID()")->fetch_row()[0];

mysqli 程序式


$link = mysqli_connect('localhost', 'user', 'pass', 'mydb');
mysqli_query($link, "INSERT INTO `t` (`name`) VALUES ('test')");
$id = mysqli_insert_id($link);

PDO


$pdo = new PDO('mysql:host=localhost;dbname=mydb', 'user', 'pass');
$pdo->exec("INSERT INTO `t` (`name`) VALUES ('test')");
$id = $pdo->lastInsertId(); // 字串型別

SQL 層面:LAST_INSERT_ID()

  • 連線級別:同一連線內,不受其他連線干擾
  • 可在 SQL 中直接使用:INSERT ...; SELECT LAST_INSERT_ID();
  • 批次插入多行時,返回第一行的自增值

INSERT INTO `t` (`name`) VALUES ('a'), ('b'), ('c');
SELECT LAST_INSERT_ID(); -- 返回第一行的 ID

連線池環境陷阱與解決

連線池複用連線時,LAST_INSERT_ID() 仍綁定於物理連線,只要同一邏輯連線內執行 INSERT 後立即查詢,即安全。


// 正確模式:同一連線內完成
$conn = pool.getConnection();
$conn->query("INSERT ...");
$id = $conn->query("SELECT LAST_INSERT_ID()")->fetchColumn();
pool.release($conn);

封裝通用 DAO 方法範例


public function insertAndGetId($table, $data) {
    $fields = implode(',', array_map(fn($k) => "`$k`", array_keys($data)));
    $placeholders = implode(',', array_fill(0, count($data), '?'));
    $sql = "INSERT INTO `$table` ($fields) VALUES ($placeholders)";
    
    $stmt = $this->pdo->prepare($sql);
    $stmt->execute(array_values($data));
    
    return $this->pdo->lastInsertId();
}

注意事項

  • REPLACE INTO / INSERT ... ON DUPLICATE KEY UPDATE 觸發更新時,LAST_INSERT_ID() 返回原有行的 ID
  • 可用 LAST_INSERT_ID(expr) 自定義返回值
  • 事務回滾後,自增值不回滾(會產生間隙)

統一使用 PDO::lastInsertId() 或 mysqli->insert_id,並在同一連線交易中完成插入與取值,是最穩健的做法。

copyright © 萬盛學電腦網 all rights reserved