ChatGPT解决这个技术问题 Extra ChatGPT

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

假设我在我的一张表中执行 MySQL INSERT,并且该表的列 item_id 设置为 autoincrementprimary key

如何让查询在同一个查询中输出新生成的主键 item_id 的值?

目前我正在运行第二个查询来检索 id 但这似乎不是一个好的做法,因为这可能会产生错误的结果......

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

没有办法从这样的 INSERT 查询中返回任何内容;为什么你认为它可能会产生错误的结果?
好吧,如果该流程由 2 个人分别执行,那么我认为您可能会得到一个重叠的流程列表 - 因为您必须执行 2 个单独的查询?
@JimFell 是的,这基本上是同一个问题,但是这个问题通常有更好的答案
使用 postgresql 然后这样做 INSERT INTO table (col1,col2) VALUES (val1,val2) RETURNING id or INSERT INTO table (col1,col2) VALUES (val1,val2) RETURNING * or UPDATE table SET col1=val1, col2=val2 WHERE 语句 RETURNING id 或 UPDATE 表 SET (col1,col2)=(val1,val2) WHERE 语句 RETURNING id 或 UPDATE 表 SET (col1,col2)=(val1,val2) WHERE 语句 RETURNING *

D
Duncan Lock

您需要使用 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() 返回的值是针对每个用户的,并且不受可能在服务器上运行的其他查询的影响来自其他用户


是的,但是如果在中间(在进程列表中的查询之间)插入了其他行怎么办?有没有办法编写插入查询以便输出它?
好的,我明白了...记录查询的最后一个插入id,即使它没有记录在结果中...$mysqli->insert_id
这将使您返回 you 插入的最后一行的 PRIMARY KEY 值,因为它是每个连接的 - 每个到服务器的连接都将为此维护它自己的值。我已经更新了答案以澄清这一点。
所以假设 3 个用户同时发布了他们的表单,我的数据库必须输入它们。我想在 table2 中添加与 table1 的每个新创建的 ID 对应的行。对于传入的数据库写入请求,并发是否得到处理,或者我是否必须在 PHP 中手动执行?
@DuncanLock,就在 - 我很欣赏这个参考。我只是在评论同时进行插入和 id 选择的请求。
L
Lii

当心!!如果尝试在 PHP 中返回此主键值,则为 LAST_INSERT_ID()

我知道这个线程没有标记 PHP,但是对于任何遇到这个答案的人来说,希望使用标准 mysql_query 调用从 PHP 脚本插入返回 MySQL 插入 id - 如果不捕获 SQL 错误,它不会工作并且不明显。

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

IMO 用于识别最后一个主键的单独 SELECT 比返回从先前 INSERT 操作生成的 AUTO_INCREMENT ID 的可选 mysql_insert_id() 函数更安全。


LAST_INSERT_ID 是每个连接的 MySQL 函数。如果您查询最后一个插入 ID,则可能有一个单独的连接执行了写入,您将获得错误的 ID。
@ExplosionPills mysql_insert_id() 也适用于每个连接,但它也会遭受奇怪的行为,如 Cliffordlife 的评论中的 stackoverflow.com/a/897374/1305910 所示——没关系,我们都应该一直在使用 mysqli
当你留下“它不起作用”时,你能澄清你的意思吗?
E
Explosion Pills

来自 LAST_INSERT_ID() 文档:

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

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


我认为如果你的表上有一个触发器来插入另一个表是值得怀疑的...... LAST_INSERT_ID() 将返回另一个表的 id 值..
C
Community

这就是你要找的东西!!!

select LAST_INSERT_ID()

这是 SQL Server 中使用的 SCOPE_IDENTITY() 函数的最佳替代方案。

您还需要记住,这仅在您的 Insert 查询之后触发 Last_INSERT_ID() 时才有效。那就是查询返回插入到模式中的 id。您无法获取特定表的最后插入 id。

有关详细信息,请通过链接 The equivalent of SQLServer function SCOPE_IDENTITY() in mySQL?


m
marc_s

您将在查询结果中收到这些参数:

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

insertId 正是您所需要的。

(NodeJS-mySql)


M
MarSoft

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

它是一个documented extension in PEP-249 DB API 标准,也适用于其他 Python MySQL 实现。


伙计,你应该为这个评论获得一枚奖章。这篇文章是今天发生的最好的事情。
U
Uladzislau Vavilau

您需要将 LAST_INSERT_ID() 函数与事务一起使用:

START TRANSACTION;
  INSERT INTO dog (name, created_by, updated_by) VALUES ('name', 'migration', 'migration');
  SELECT LAST_INSERT_ID();
COMMIT;

http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id

此函数将返回表中最后插入的主键。


我原以为这应该是公认的答案。交易可能没有必要,但对我来说似乎是最安全、最清晰的方法。
P
Paulo A. Costa

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

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'
);

这似乎不是一个好主意?如果 2 个客户端同时调用该函数,他们会认为他们正在插入相同的 id,而实际上他们不是......插入时会稍微慢一些,并在不知道的情况下获取下一个 ID。
A
AlexSp3

只需使用:

$last_id = mysqli_insert_id($conn);

多亏了谷歌,我实际上在这里偶然发现了这个答案的 php 版本,所以我投票给了这个答案。虽然从技术上讲,OP 并没有要求 php,但这可能对许多在这里绊倒的人有所帮助。
非常感谢阿纳夫!我
O
Olafnyr

如果您使用的是 PHP:在 PDO 对象上,您可以在插入后简单地调用 lastInsertId 方法。

否则,使用 LAST_INSERT_ID 您可以获得如下值:SELECT LAST_INSERT_ID();


H
Hamza Saeed

我将 return $this->db->insert_id(); 用于 Codeigniter


L
Luciano Coelho

做这个:

$idc = DB::table('tb_clients')->insertGetId([
                'ide'                   => $ide,
                'nome'                  => $nome,
                'email'                 => $email 
            ]);

在 $idc 你会得到最后一个 id


S
Singh G

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

生成一个随机键并将其插入到创建新行的表中。然后您可以使用该键来检索主键。使用更新来添加数据和做其他事情。

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

我真的不推荐这个,除非你没有其他选择。


您可以使用 PDO 对象并获取最后一个插入 ID。您还可以在同一个事务中使用 SELECT LAST_INSERT_ID() (如果您有几个人插入,使用同一个事务非常重要)。您提出的方法不能保证 - 尽管不太可能,但您可能会在键上发生冲突。此外,通过更新添加所有数据意味着您不能有非空字段,这也会导致更差的数据完整性。最后,随机密钥的插入和更新可能会中断,您将处于不需要的状态并且没有数据完整性。
我不知道为什么张贴者建议将插入和更新作为两个不同的操作;当我不得不使用这种方法时,我通过代码生成了随机键,并将它与所有记录字段一起用于插入查询。老实说,使用 UUID 在统计上不可能发生冲突(16 ^ 32 种可能性)。我发现这种方法是 OP 问题的有效解决方案