【问题标题】:Get the new record primary key ID from MySQL insert query?从 MySQL 插入查询中获取新记录的主键 ID?
【发布时间】:2022-01-22 19:38:01
【问题描述】:

假设我在我的一张表中执行 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 *

标签: mysql insert key auto-increment


【解决方案1】:

你需要使用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 选择的请求。
【解决方案2】:

当心!! LAST_INSERT_ID() 如果试图在 PHP 中返回这个主键值。

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

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

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

【讨论】:

  • LAST_INSERT_ID 是一个基于连接的 MySQL 函数。如果您查询最后一个插入 ID,则可能有一个单独的连接执行了写入操作,而您的 ID 错误。
  • @ExplosionPills mysql_insert_id() 也适用于每个连接,但它也会遭受奇怪的行为,如在 Cliffordlife 的评论中看到的stackoverflow.com/a/897374/1305910 ——没关系,我们都应该一直使用mysqli
  • 你能解释一下你留下“它不会工作”的意思吗?
【解决方案3】:

来自LAST_INSERT_ID() 文档:

生成的 ID 在服务器中以每个连接为基础进行维护

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

【讨论】:

  • 我认为如果你的表上有一个触发器来插入另一个表是值得怀疑的...... LAST_INSERT_ID() 将返回另一个表的 id 值..
【解决方案4】:

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

select LAST_INSERT_ID()

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

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

更多详情请点击链接The equivalent of SQLServer function SCOPE_IDENTITY() in mySQL?

【讨论】:

    【解决方案5】:

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

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

    insertId 正是您所需要的。

    (NodeJS-mySql)

    【讨论】:

      【解决方案6】:

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

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

      【讨论】:

      • 老兄,你应该为这条评论获得一枚奖章。这篇文章是今天发生的最好的事情。
      【解决方案7】:

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

      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。
      【解决方案8】:

      您需要将 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

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

      【讨论】:

        【解决方案9】:

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

        【讨论】:

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

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

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

        【讨论】:

          【解决方案11】:

          我使用 return $this->db->insert_id(); 作为 Codeigniter

          【讨论】:

            【解决方案12】:

            这样做:

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

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

            【讨论】:

              【解决方案13】:

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

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

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

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

              【讨论】:

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