2016-12-30 204 views
2

manual它指出PDO的LastInsertId是如何工作的?

返回最後插入的行,或最後的值的ID從一個序列對象,這取決於底層驅動。

在哪裏,如果沒有$name變量作爲第一個參數傳遞給PDO::LastInsertID(),它會檢查被插入到數據庫的最後一行。這個函數的狀態也可以通過所聲明的驅動程序來確定是否工作,如果您使用的是MySQL,那麼您可以很好地支持,但是如果您使用的數據庫不支持OIDAUTO_INCRAMENT表定義,PDO::LastInsertId()最有可能不工作。

這一切都很好,很有道理,但這是如何實現的?

我明白PDO只是數據庫連接的另一個抽象層,但我們也在討論mysqli_insert_id函數。

我對這種方法的想法是,有一個緩存(not on PHP's side),我後來發現在從手冊頁上的warezthebeef at gmail dot com讀取這段代碼時是正確的。

// Assume $dbh connection handle is already established 
$sql = "INSERT INTO product (product_name) OUTPUT INSERTED.product_id VALUES (?)"; 
$sth = $dbh->prepare($sql); 
$sth->execute(array('widgets')); 
$temp = $sth->fetch(PDO::FETCH_ASSOC); 

echo "<pre>",print_r($temp),"</pre>"; 

這將顯示:

Array 
(
    [product_id] => E1DA1CB0-676A-4CD9-A22C-90C9D4E81914 
) 

這是導致數據庫中的表將包含的行product_id,並在SQL你指出來輸出該行插入後,這將是id爲更多共同條件,並且如果使用AUTO_INCRAMENT將只是一個單一的數字。 (你可以通過看here更多進去)(這也與RETURNING SQL關鍵字實現)

所以,從某種意義上說,如果我們不希望使用PDO::LastInsertID()方法,我們可以只使用:

$sql = "INSERT INTO table (name, country) OUTPUT INSERTED.id VALUES (?,?)"; 
$sth = $dbh->prepare($sql); 
$sth->execute(['jack', 'Australia']); 
$temp = $sth->fetch(PDO::FETCH_ASSOC); 

echo $temp['id'] 

哪個應輸出我們剛剛插入到數據庫中的新ID,注意我們使用的主要或OID列是AUTO_INCRAMENT

所以在我的腦海裏(這就是爲什麼我問這個問題)PDO可能會緩存數據在PHP's Temp然後檢索或寫在方法被調用時,可能會添加RETURNING id或這樣的,但它不是它的工作方式,因爲它基於OID列。

我回答了問題的一半 - 我只是想知道的方法實際上是如何存儲的最後一個ID或者將其拉

謝謝!

+0

我猜想它使用mysql的最後一個插入id功能。 http://dev.mysql.com/doc/refman/5.7/en/information-functions.html#function_last-insert-id – bassxzero

+0

注意這一點,你可以直接用'$ lastInsertId = $ dbh-> lastInsertId();' – cmorrissey

回答

2

確切的實現取決於驅動程序。我只能描述它如何適用於MySQL,因爲這正是我所熟悉的。

正如我們在答案中描述到How does MySqlCommand.LastInsertedId work?問題:

如果MySQL成功執行客戶端請求的查詢,那麼MySQL發送OK_Packet作爲響應。

在OK_Packet的MySQL的有效載荷包括最後插入的ID(見上面鏈接文檔):

Type  | Name   | Description 
------------|----------------|----------------------------------- 
int<1>  | header   | [00] or [fe] the OK packet header 
int<lenenc> | affected_rows | affected rows 
int<lenenc> | last_insert_id | last insert-id 
... 

在服務器沒有select last_insert_id()被執行以填充該數值到OK_packet。驅動程序從數據包中檢索最後插入的ID,然後PDO從驅動程序中檢索值。

+0

如果你真的想在代碼中追溯它,我建議從https://github.com/php/php-src/blob/PHP-7.1.0/ext開始/pdo_mysql/mysql_driver.c#L288並將其追蹤到https://github.com/php/php-src/blob/PHP-7.1.0/ext/mysqlnd/mysqlnd_wireprotocol.c#L2839 – VolkerK

+0

感謝您的回答! :-) – Jek