在插入之前清除LAST_INSERT_ID()以告知返回的内容是否来自我的插入

Boh*_*ian 12 mysql auto-increment last-insert-id

LAST_INSERT_ID() 通过自动增量列返回为当前连接生成的最新id,但是如何判断该值是来自最后一个插入而不是来自同一连接上的先前插入?

假设我正在使用池中的连接,该连接可能在我获得连接之前插入了一行,并且我执行了一个条件插入:

insert into mytable (colA)
select 'foo' from bar
where <some condition>;
select LAST_INSERT_ID();
Run Code Online (Sandbox Code Playgroud)

我无法知道返回的值是否来自我的插入.

我想到的一种方式是:

@previousId := LAST_INSERT_ID();
insert into mytable (colA)
select 'foo' from bar
where <some condition>;
select if(LAST_INSERT_ID() != @previousId, LAST_INSERT_ID(), null);
Run Code Online (Sandbox Code Playgroud)

有没有办法"清除"该LAST_INSERT_ID()值,所以我知道如果返回非零值,它是由我的SQL引起的新值?

egg*_*yal 10

我同意@Digital Chris的回答,你不应该通过检查返回的值来确定插入是成功还是失败LAST_INSERT_ID():有更多的直接路由,例如受影响的行数.尽管如此,仍然可能需要从中获得"干净"的价值LAST_INSERT_ID().

当然,您提出的解决方案(与插入前的值进行比较)的一个问题是,可能会发生插入成功并且其指定的自动递增值恰好与先前插入的值相同(可能是另一张桌子).因此,比较可能导致插入失败的假设,而事实上它已成功.

我建议,如果可能的话,你可以避免使用LAST_INSERT_ID()SQL函数而不是mysql_insert_id()API调用(通过你的驱动程序).正如后者的文件所述:

mysql_insert_id()返回0如果前面的语句未使用的AUTO_INCREMENT价值.如果需要保存该值以供日后使用,请务必mysql_insert_id()在生成该值的语句后立即调用.

[ deletia ]

之所以之间的差异LAST_INSERT_ID(),并mysql_insert_id()LAST_INSERT_ID()由易在脚本中使用,同时mysql_insert_id()试图提供什么发生了更准确的信息AUTO_INCREMENT栏.

无论如何,如下所述:LAST_INSERT_ID(expr)

如果expr作为参数给出,则参数LAST_INSERT_ID()的值由函数返回,并记住作为要返回的下一个值LAST_INSERT_ID().

因此,在执行之前INSERT,您可以重置:

SELECT LAST_INSERT_ID(NULL);
Run Code Online (Sandbox Code Playgroud)

这也应该重置返回的值mysql_insert_id(),尽管文档建议调用必须在一个或一个语句中进行 - 可能需要测试来验证.无论如何,如果需要,创建这样的无操作语句应该是非常简单的:LAST_INSERT_ID(expr)INSERTUPDATE

INSERT INTO my_table (my_column) SELECT NULL WHERE LAST_INSERT_ID(NULL);
Run Code Online (Sandbox Code Playgroud)

值得注意的是,还可以设置identitylast_insert_id系统变量(但是这些只会影响返回的值,LAST_INSERT_ID()而不会影响mysql_insert_id()):

SET @@last_insert_id := NULL;
Run Code Online (Sandbox Code Playgroud)


Dig*_*ris 6

你推测你可能会得到前一个LAST_INSERT_ID(),但实际上,我不知道这种情况会发生在哪里.如果您正在进行条件插入,则必须在执行后续步骤之前检查它是否成功.例如,您将始终用于ROW_COUNT()检查插入/更新的记录.伪代码:

insert into mytable (colA)
select 'foo' from bar
where <some condition>;

IF ROW_COUNT() > 0
    select LAST_INSERT_ID();
    -- ...use selected last_insert_id for other updates/inserts...
END IF;
Run Code Online (Sandbox Code Playgroud)


Boh*_*ian 5

使用ROW_COUNT()以确定您的条件插入尝试是成功的,然后返回LAST_INSERT_ID()或基于一个默认值:

select IF(ROW_COUNT() > 0, LAST_INSERT_ID(), 0);
Run Code Online (Sandbox Code Playgroud)