从mysql插入查询中获取新记录的主键ID?


249

好的,可以说我正在INSERT对一个表进行mysql操作,并且该表的列item_id设置为autoincrementprimary key

如何获得查询以item_id在同一查询中输出新生成的主键的值?

目前,我正在运行第二个查询来检索ID,但是考虑到这可能会产生错误的结果,这似乎不是一种好习惯。

如果这不可能,那么确保我检索正确ID的最佳实践是什么?


1
无法从这样的INSERT查询中返回任何内容;您为什么认为它可能会产生错误的结果?
爆炸药

4
好吧,如果该流程由2个人分别执行,那么我认为您会得到一个重叠的流程列表-因为您必须执行2个单独的查询?
艾米·内维尔


@JimFell是的,这基本上是相同的问题,但是总体来说,这个问题要好得多
RozzA

1
使用postgresql然后执行以下操作:INSERT INTO表(col1,col2)VALUES(val1,val2)RETURNING id或INSERT INTO表(col1,col2)VALUES(val1,val2)RETURNING *或UPDATE表SET col1 = val1,col2 = val2 WHERE语句RETURNING id或UPDATE表SET(col1,col2)=(val1,val2)WHERE语句RETURNING id或UPDATE table SET(col1,col2)=(val1,val2)WHERE语句
RETURNING

Answers:


326

您需要使用以下LAST_INSERT_ID()函数:http : //dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id

例如:

INSERT INTO table_name (col1, col2,...) VALUES ('val1', 'val2'...);
SELECT LAST_INSERT_ID();

这将让你背PRIMARY KEY的最后一排的价值插入:

生成的ID在每个连接的服务器中维护。这意味着函数返回给定客户端的值是为该客户端影响AUTO_INCREMENT列最新语句生成的第一个AUTO_INCREMENT值。

因此,通过返回的值LAST_INSERT_ID()是每用户是不会受到影响的,可能在服务器上运行的其他查询其他用户


8
是的,但是如果在过渡期间(过程列表中的查询之间)插入了另一行怎么办?有什么方法可以编写插入查询,以便输出该查询?
艾米·内维尔

好的,我看到了...即使没有在查询结果中记录该查询的最后一个插入ID ... $ mysqli-> insert_id
Amy Neville

27
这将让你背PRIMARY KEY的最后一排的价值,你插入,因为这是每个连接-每个连接到服务器将保持它的这种自身的价值。我已经更新了答案以澄清这一点。
Duncan Lock

因此,假设3个用户同时发布了他们的表单,而我的数据库必须输入它们。我想在table2中添加与table1的每个新创建的ID对应的行。对于传入的数据库写请求,是否需要并发处理,还是必须在PHP中手动进行?
bad_keypoints 2013年

如果在执行table1插入时,数据库知道您要插入到table2中的所有信息,那么您可以使用触发器来执行此操作,或者将其组合到查询中。如果没有,那么您将需要使用多个查询-即在PHP中进行。这取决于第二次插入的数据是什么以及来自何处。
Duncan Lock

21

谨防 !! 如果试图在PHP中返回此主键值,则为“ LAST_INSERT_ID()”的值。

我知道此线程未标记为php,但对于遇到此问题的任何人,他们都希望使用标准的mysql_query调用从PHP脚本化插入中返回MySQL插入ID-这将无法工作,并且在没有捕获SQL错误的情况下也不明显。

较新的mysqli支持多个查询 -LAST_INSERT_ID()实际上是原始查询的第二个查询。

与返回从前一个INSERT操作生成的AUTO_INCREMENT ID的可选mysql_insert_id()函数相比,IMO单独的SELECT来标识最后一个主键更为安全。


7
LAST_INSERT_ID是每个连接的MySQL函数。如果查询最后一个插入ID,则可能是单独的连接已执行写操作,并且ID错误。
爆炸药

@ExplosionPills mysql_insert_id()也适用于每一个连接的基础,但它也受到这里看到奇怪的行为stackoverflow.com/a/897374/1305910由Cliffordlife评论-没关系,我们都应该一直在使用mysqli
RozzA

您能否澄清当您停留在“它不会起作用”时的意思?
约翰·克特吉克

18

LAST_INSERT_ID()文档中:

生成的ID在每个连接的服务器中维护

也就是说,如果您同时有两个对脚本的单独请求,它们将不会彼此影响LAST_INSERT_ID()(除非您正在使用持久连接)。


2
我认为如果您的表上有一个触发器可以插入另一个表中,这是值得怀疑的。.LAST_INSERT_ID()将返回另一个表的ID值
。–

15

在这里您正在寻找!

select LAST_INSERT_ID()

这是SCOPE_IDENTITY()正在使用的功能的最佳替代方案SQL Server

您还需要记住,这只有Last_INSERT_ID()在您的用户触发后才有效Insert查询之后。也就是说,查询返回插入到架构中的ID。您无法获取特定表的最后插入的ID。

有关更多详细信息,请通过链接。是否等效于mySQL中SQLServer函数SCOPE_IDENTITY()?


6

如果在插入行之前需要该值:

CREATE FUNCTION `getAutoincrementalNextVal`(`TableName` VARCHAR(50))
    RETURNS BIGINT
    LANGUAGE SQL
    NOT DETERMINISTIC
    CONTAINS SQL
    SQL SECURITY DEFINER
    COMMENT ''
BEGIN

    DECLARE Value BIGINT;

    SELECT
        AUTO_INCREMENT INTO Value
    FROM
        information_schema.tables
    WHERE
        table_name = TableName AND
        table_schema = DATABASE();

    RETURN Value;

END

您可以在插入内容中使用它:

INSERT INTO
    document (Code, Title, Body)
VALUES (                
    sha1( concat (convert ( now() , char), ' ',   getAutoincrementalNextval ('document') ) ),
    'Title',
    'Body'
);

1
这似乎不是一个好主意?如果2个客户端同时调用该函数,则他们会以为实际上插入的ID其实不是。...插入时会稍慢一些,并且在不知道的情况下获得下一个ID。
CarCar '17

5

您将在查询结果中收到以下参数:

    "fieldCount": 0,
    "affectedRows": 1,
    "insertId": 66,
    "serverStatus": 2,
    "warningCount": 1,
    "message": "",
    "protocol41": true,
    "changedRows": 0

insertId正是你所需要的。

(NodeJS-mySql)


4

如果在python中使用pymysql,则可以从游标中使用cursor.lastrowid


2

只需使用“ $ last_id = mysqli_insert_id($ conn);”


2
实际上我在这里偶然发现了这个答案的php版本,这要归功于google,所以我投票赞成了这个答案。虽然从技术上讲OP并不需要php,但这对很多在这里绊倒的人也会有所帮助。
摄影师Britt

非常感谢Arnav!I
JuanSedano '19



0

我只想在PHP中分享我的方法,其中有些人可能发现它不是一种有效的方法,但是比其他可用方法好100倍。

生成一个随机密钥,并将其插入到表中以创建新行。那么您可以使用该键来检索主键。使用更新来添加数据并执行其他操作。

这样做有助于保护行并拥有正确的主键。

除非您没有其他选择,否则我真的不建议您这样做。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.