【问题标题】:How does PDO know last inserted id in MySQL?PDO 如何知道 MySQL 中最后插入的 id?
【发布时间】:2011-05-15 03:01:45
【问题描述】:

编辑:这个问题的标题最初是:Doctrine 如何知道 MySQL 中最后插入的 id? 并且与 Doctrine ORM 映射器有关。经过一番挖掘,我发现这个问题与 Doctrine 无关,而是与 PDO_MySQLMySQL C API 以及最后 - 与 MySQL 客户端服务器有关沟通。我决定更改标题,所以也许有人会找到他/她的问题的答案。

对于那些不使用 Doctrine 的人:我很好奇,为什么如下:

mysql_query("INSERT INTO category (name) VALUES('cat')");
echo mysql_insert_id();

或类似的:

$pdo->exec("INSERT INTO category (name) VALUES('cat')");
echo $pdo->lastInsertId();

将导致日志中只有一个位置(没有单独的SELECT LAST_INSERT_ID()):

1701 Query    INSERT INTO category (name) VALUES ('cat')

原问题:

我有 2 张桌子:

category(id,name)
product(id, name, categoryId)

我创建了新的类别对象和产品对象。我将类别对象分配给产品对象。我没有设置任何ID:

$product = new Product();
$product->name = 'asdf';

$category = new Category();
$category->name = 'cat';

$product->Category = $category;

之后我刷新了连接并检查了 MySQL 日志:

1684 Query  START TRANSACTION
1684 Query  INSERT INTO category (name) VALUES ('cat')
1684 Query  INSERT INTO product (name, categoryid) VALUES ('asdf', '312')
1684 Query  COMMIT

Doctrine 怎么知道新创建的类别 id 是 312?日志中没有其他内容。

【问题讨论】:

    标签: php mysql doctrine pdo communication-protocol


    【解决方案1】:

    我做了一些研究并浏览了一些源代码,所以我的回答可能有点错误且不准确。

    首先,这与Doctrine 没有真正的关系。 Doctrine 使用 PDO_MYSQL。但在内部 PDO_MYSQL 使用与 mysql_insert_id 函数相同的东西 - 本机 MySQL C API 函数 - mysql_insert_id

    没有单独的SELECT LAST_INSERT_ID() 的原因在于,在执行语句后(在我的示例中为INSERT),服务器响应数据和包含在OK Packet 中的一些其他内容 em>),包括insert_id。因此,当我们触发mysql_insert_id() 时,我们没有连接到服务器,接收insert_id - mysql 库不需要这样做 - 它已经从上次执行查询时存储了这个值(至少我在分析文件libmysql.c)

    OK 数据包在这里描述:MySQL Generic Response Packets - OK Packet

    【讨论】:

    • 这就是为什么我们可以使用它,而不用担心查询竞争。谢谢。
    【解决方案2】:

    【讨论】:

    • 但这会反映在日志中,不是吗?
    • @Pekka 一个没有根据的猜测:日志是否可以配置为写入SELECTs?
    • @jensgram 可以是 - 或者可以配置为显示函数调用的结果(即LAST_INSERT_ID())。我不知道查询日志是如何工作的
    • 我已经做了类似于INSERT INTO foo2 (id,text) VALUES(LAST_INSERT_ID(),'text'); 的事情,并且我在日志中拥有字符串LAST_INSERT_ID()...,而不是id 本身的值。
    • @prostynick 你试过简单的SELECT 吗?你也能在日志中找到这个吗?
    【解决方案3】:

    last_insert_id 仅适用于 AUTO_INCREMENT 列。如果您手动将值插入AUTO_INCREMENT 列,它将不起作用。

    这个原则会起作用,因为它就像给它分配一个NULL(尽管你从来没有专门写过那个)。这会触发自动递增并为last_insert_id() 提供一个值。

    我在此处添加了一个 jpg,以便您查看。希望对您有所帮助!

    【讨论】:

    • 这并没有解释学说实际上是如何检索值的。没有检索到 last_insert_id 的查询。
    • 这个答案与问题无关。
    猜你喜欢
    • 2012-05-31
    • 2013-05-26
    • 2010-12-12
    • 1970-01-01
    • 2012-05-27
    相关资源
    最近更新 更多