PDO的LastInsertId如何实际工作?

时间:2016-12-30 15:44:50

标签: php mysql database pdo

manual上声明

  

返回最后插入行的 ID ,或序列对象中的最后一个值,具体取决于底层驱动程序。

如果没有$name变量作为PDO::LastInsertID()的第一个参数传递,它将检查插入数据库的最后一行。如果您正在使用MySQL,那么此函数的状态也可以确定是否正常工作,因为您支持得很好,但是如果您使用的数据库不是t支持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,注意我们使用AUTO_INCRAMENT主要或OID列。

所以在我的脑海里(这就是我问这个问题的原因)PDO可以缓存PHP's Temp中的数据,然后在调用方法时检索或写入数据,可能会添加RETURNING id或这样,但这不是它的工作方式,因为它基于OID列。

我回答了问题的一半 - 我只是想知道该方法实际存储最后一个ID或拉取它

谢谢!

1 个答案:

答案 0 :(得分: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从驱动程序中检索该值。