【问题标题】:MySQL+PHP: getting last_id of multiple/composite primary keyMySQL + PHP:获取多个/复合主键的last_id
【发布时间】:2011-11-03 12:00:27
【问题描述】:

我需要获取最后插入的具有多列主键的表的 id。

  • 那些表没有 AUTOCOUNT 列。
  • 我正在使用参数化查询(任意顺序)
  • 使用 PHP (5.3) 和 MySQLi 模块
  • 任意 INSERT SQL 查询。 (任何格式)

例如:

Table: foo
Primary key: [ group_id , user_id ]
Query: INSERT INTO foo (group_id, user_id, name, email) VALUES (?, ?, ?, ?);
Parameters: array(34,15,"John","john@example.com")

结果:$last_id = $mysqli->insert_id ?: getInsertedId();

34,15

此时我有一个名为 getPK() 的函数,它返回我:

array("group_id","user_id");

我现在需要的是实现 getInsertedId()。在不使用 SQL 解析器的情况下,哪一种方法更简单?

我很确定这个问题已经有了答案,但我找不到任何东西......

更新

我问这个问题的原因是因为我有一个类可以控制与 MySQL 数据库相关的所有内容(个人框架的一部分)。我有一种称为 set() 的方法,其中传递了查询(如 UPDATE、INSERT、DELETE 等)。我还有其他特定的方法,例如 insert(),其中传递了数组。

我有一个变量用于存储 last_inserted_id。以后可以随时调用该变量。我在具有多个主键的不同系统中有许多表。 使用 insert() 方法时,我可以设置 last_inserted_id 值,但是当某些系统使用 set() 方法时,我无法检索该值并且我必须返回 0。我想改变这种行为。

我想用上面的例子来简化我的解释。

更新 2

并非所有系统都由我自己控制。例如,其中一个系统调用soap 方法,在该方法中发送查询以执行(任何类型的查询)。这些由 set() 方法处理。然后还有其他soap方法可以检索最后一个id。为了保持一致性,我想返回该值。

【问题讨论】:

  • 如果指定group_iduser_id,为什么要在INSERT之后从数据库中取回它们?
  • 在解决代码问题时,您可能想再看一下该表结构。它似乎只存在于 1NF 中,尽管我无法仅通过列名和一行数据来确定。

标签: php mysql composite-primary-key lastinsertid


【解决方案1】:

您可以添加一个Timestamp 列,当记录为INSERTED 时自动初始化为当前时间戳,并且每次更新记录时更新:

ALTER TABLE MyTable
  ADD COLUMN InsertTS TIMESTAMP DEFAULT CURRENT_TIMESTAMP
, ADD INDEX InsertTS_ind (InsertTS) ;

您还要确保没有其他查询、函数或触发器更改该值。然后,您可以使用查询找到时间戳最高的记录的PK:

SELECT group_id, user_id
FROM MyTable
ORDER BY InsertTS DESC
LIMIT 1 ;

注意只有在您在表格中还没有获得自动初始化和/或自动更新值的时间戳时才能执行此操作。 p>

【讨论】:

  • (+1) 实际上我确实考虑过这一点……但我不喜欢在 MySQL 中没有办法做到这一点的想法。如果在插入/更新之后,您可以检索实际插入/更新的值,那就太好了,例如:SELECT LAST_INSERT FROM TABLE; (并返回插入的行)。这对我真的很有帮助......
  • @lepe:是的,LAST_INSERT_ID() 适用于每个连接,但仅适用于自动生成的 ID。我的答案会有所不同 - 不是每个连接,而是通过所有连接的插入。当 2 条记录具有相同的时间戳时,也需要注意这种情况。
  • 另一种可能性是将(group_id, user_id) 键从PRIMARY 更改为UNIQUE 并添加一个自动递增的PK。
  • 这是危险!如果您有多个用户并且两个用户同时添加一条记录,那么两者最终都会得到相同的记录。
  • @ypercube 我的意思是如果两个用户同时存储不同的数据,然后按日期获取最后一个插入行。两者之一将得到错误的行。
【解决方案2】:

正如 Phil 在评论中指出的那样,MySQL LAST_INSERT_ID() 只能返回自动生成的值 (AUTO_INCREMENT)。

此外,您不能在多列上使用 auto_increment:如果您有多个主键,则 auto_increment 只能在 1 列上使用。

总之,在您的情况下,您无法使用 LAST_INSERT_ID() 插入密钥。

一种解决方案是在 PHP 中处理这种情况,以便您的 getInsertedId() 方法返回为插入提供的主键的值。

【讨论】:

  • “一个解决方案是在 PHP 中处理这种情况,以便您的 getInsertedId() 方法返回为插入提供的主键的值。”其实这就是这个问题的意义所在。
  • 请再读一遍。我说了这么多只是为了得出结论“在你的情况下,你不能使用 LAST_INSERT_ID() 插入密钥。”。一旦清楚了,我就会为你提出一个解决方案。干杯
  • 那么这只是编码,与 Mysql 无关(正如您的问题所建议的那样)。我们不知道您的代码或有关其架构的任何信息,所以这里有一个答案:使用 PHP 变量来存储 ids,然后使用 return array($group_id, $user_id);... 返回它们
  • 好的,我再次阅读了您的问题,如果我理解正确,set() 方法采用字符串 SQL 查询,因此您无法获取变量..嗯,恐怕问题出在你的代码架构上。您希望有一个控制一切的类,但实际上它并不能控制一切(使用 set(),您无法控制查询)。
  • 不一定必须在 PHP 中修复。例如,可以在表中添加触发器以在 INSERT 之后更新 insert_id(但不是那么好)。或者也许 MySQL 将我需要的信息存储在某个地方。我越想越得出结论,没有这样的信息......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-05
  • 1970-01-01
  • 2012-10-08
  • 1970-01-01
  • 2016-07-04
  • 1970-01-01
  • 2014-12-07
相关资源
最近更新 更多