【问题标题】:(mysql, php) How to get auto_increment field value before inserting data?(mysql, php) 如何在插入数据前获取 auto_increment 字段值?
【发布时间】:2010-02-12 11:36:51
【问题描述】:

我正在将图像文件上传到存储服务器。在上传之前,我应该编写文件名,其中包含 AUTOINCREMENT VALUE(例如,12345_filename.jpg)。

如何在插入数据库之前获得自动增量值?

我只看到一个解决方案

  1. 插入空行
  2. 获取它的自动增量值
  3. 删除此行
  4. 使用 p.1 中的自动增量值插入包含真实数据的行

还有其他解决办法吗?

谢谢

【问题讨论】:

  • 你概述的方法会很糟糕;如果另一个用户在 3 和 4 之间开始该路径怎么办?插入行,获取 id,然后更新该行。
  • 如果另一个用户将在 3 和 4 之间开始操作,则不会发生任何事情,因为这个自动增量值已经被保留,不会再被 mysql 分配一次。更新很好,但如果上传失败,我应该注意删除空行。

标签: php mysql


【解决方案1】:

插入完成后,自动增量值由数据库自己生成;这意味着在执行实际插入查询之前您无法获得它。

您提出的解决方案不是经常使用的解决方案——应该是:

  • 插入一些半空数据
  • 获取已生成的自增值
  • 使用该自动增量值进行计算
  • 更新行以放置新的/完整的数据 - 使用前面在 update 查询的 where 子句中生成的自动增量来识别正在更新的行。

当然,作为安全预防措施,所有这些操作都必须在事务中进行(以确保“全有或全无”行为)


作为伪代码:

begin transaction
insert into your table (half empty values);
$id = get last autoincrement id
do calculations
update set data = full data where id = $id
commit transaction

【讨论】:

  • 出于安全考虑,我也不建议在图像文件名中使用数据库行的 ID。相反,使用类似uniqid().
  • 这是我的问题,真的 - 如果您处于未提交的事务中,您是否真的获得了生成的新 ID?
【解决方案2】:

好吧,试试这个:

$query = "SHOW TABLE STATUS LIKE 'tablename'";
$result = mysql_query($query);
$row = mysql_fetch_assoc($result);
var_dump($row);

输出:

array(18) {
[...]
["Auto_increment"]=> string(4) "3847"
[...]
}

这将是您的下一个 auto_increment ID。

【讨论】:

  • 我猜原因可能是这里已经多次提到:知道当前/下一个 id 并不能保证在您实际执行插入时得到这个 id。
  • 是的,但是如果您知道在此期间不会有其他插入查询,您可以毫无问题地使用它。我在一些项目中遇到过这种情况,我可以安全地使用它。
  • 同意。如果您完全控制应用程序并且完全确定在此期间不会发生其他插入查询,这可能是可用的(但我认为这种情况非常罕见)。
  • 这应该是正确的答案。这让我想知道现在人们有什么问题。
  • 是的,并发连接不是一个好主意,但就我而言,这对于单元测试来说很好。我需要将在表格中插入内容的方法的结果与预期结果进行比较,这非常适合预测我将获得的 ID。
【解决方案3】:

如果您使用 PDO,这里有一个“单行”的解决方案

$nextId = $db->query("SHOW TABLE STATUS LIKE 'tablename'")->fetch(PDO::FETCH_ASSOC)['Auto_increment'];

tablename 被您的表替换。

【讨论】:

    【解决方案4】:

    没有解决办法。当您插入新行时,您会获得自动增量值,句号。插入和删除无济于事,因为下一个自动增量值会更高。如果可能有多个客户端同时与数据库通信,您无法预测下一个值,因为它可能会在您的猜测和实际插入之间增加。

    寻找不同的解决方案。要么插入一行并稍后更新它,要么为文件名生成一个独立于自增 id 的 id。

    【讨论】:

      【解决方案5】:

      @Pascal Martin 提出了一个很好的观点。在这种情况下,我个人喜欢添加另一个 ID 列,其中包含一个随机的 16 位 ID(出于安全原因,这也是 Web 应用程序和网站上的“公共”ID)。您可以在应用程序中预先设置此随机 ID,使用它,然后在实际创建记录时设置。

      【讨论】:

        【解决方案6】:

        使用单独的表作为计数器,如 postgresql 序列,并且不要在主表中使用 auto_increment。

        【讨论】:

          【解决方案7】:

          INSERT INTO CONTACTS1 (firstname, lastname) values('hi', select auto_increment from information_schema.TABLES where TABLE_NAME='CONTACTS1' and TABLE_SCHEMA='test')

          其中 ID 是主键和自动编号列。

          【讨论】:

            【解决方案8】:

            好吧,这已经过时了,但如果其他人需要它。

            您可以在“information_schema”表中获得这种值,您可以在其中执行类似的操作

            select AUTO_INCREMENT from TABLES where TABLE_SCHEMA = 'You're Database' and TABLE_NAME = 'Table Name'
            

            所以这种元数据总是存储在 Information_schema 中。

            【讨论】:

            • 这很容易出现竞争条件。如果两个客户端同时获得一个 ID,他们将获得相同的 ID,并且可能会践踏彼此的数据。如果您关心并发性(并且您应该关心),那么您从 AUTO_INCREMENT 获得的 ID 是无用的,直到它被分配到数据库中的一行,因为在此之前它不能保证是唯一的。
            猜你喜欢
            • 2019-12-15
            • 1970-01-01
            • 1970-01-01
            • 2014-02-04
            • 1970-01-01
            • 1970-01-01
            • 2015-12-10
            • 2012-10-19
            • 2015-08-23
            相关资源
            最近更新 更多