从MySQL获取最后一条记录

3
我正在使用mysql并遇到一些问题。我想检索插入的最后一行。 <<以下是详细信息>> 以下是我创建表的方式。 create table maxID (myID varchar(4)) 我插入了四个值,如下所示。
insert into maxID values ('A001')
insert into maxID values ('A002')
insert into maxID values ('A004')
insert into maxID values ('A003')

当我执行select myID, last_insert_id() as NewID from maxID时,我得到以下输出
myId NewID
A001   0  
A002   0  
A004   0  
A003   0    

当我尝试下面的代码时, select myId, last_insert_id() as NewID, @rowid:=@rowid+1 as myrow from maxID, (SELECT @rowid:=0) as init 我得到以下输出。
myId NewID  rowid
A001   0      1
A002   0      2
A004   0      3
A003   0      4

然而,当我使用代码 select myId, last_insert_id() as NewID, @rowid:=@rowid+1 as myrow from maxID, (SELECT @rowid:=0) as init where @rowid = 4 时,我会收到错误信息 Uknown column 'myrow' in where clause
当我使用 where @rowid=4 时,表中没有任何数据。

链接以处理数据

注意: 这里我只是使用 4 来获取所需的输出。稍后我可以从查询 (select max(rowid) from maxID) 中获取它。
请建议如果我只想看到最后一条记录即 A003 我需要做什么。
感谢您的时间。

更新:

我已经有数百万条数据在我的表中,因此我不能像下面建议的那样添加新列。


谢谢所有的评论...但是在我的情况下有没有找到最后插入记录的方法呢? - Fahim Parkar
成千上万的数据并不意味着太多。关系型数据库是为处理数百万条数据而构建的。如果您无法处理数百万条数据,则一直选择错误地使用数据库。 - Edwin Buck
6个回答

5

差不多完成了。 您已成功获取插入订单。 所以:

select myId, @rowid:=@rowid+1 as myrow from maxID, (SELECT @rowid:=0) as init ORDER BY myrow desc LIMIT 1;

我的控制台显示以下内容:

mysql> select myId, @rowid:=@rowid+1 as myrow from maxID, (SELECT @rowid:=0) as
init ORDER BY myrow desc LIMIT 1;
+------+-------+
| myId | myrow |
+------+-------+
| A003 |     4 |
+------+-------+
1 row in set (0.00 sec)

演示

更新

Yak是正确的。我的解决方案不是确定性的。也许它适用于少量记录。我发现了大量关于默认排序的SELECT语句的不可靠性的帖子(例如这里)。 下一步:

  • 在什么条件下默认的SELECT排序与插入顺序匹配?
  • 是否有可能在没有增量id或插入时间戳的情况下获取表中最后插入的记录?

我知道这不是一个答案,但是说明了问题的限制。


哎呀,我简直不敢相信。我不知道为什么我只想用 myrow=4 这个解决方案。我没想到这个解决方案... 非常感谢 :) :) - Fahim Parkar
我需要再等待22个小时才能授予悬赏 :( 我明天会给你悬赏积分... - Fahim Parkar
请纠正我如果我错了,但我理解你的策略依赖于SELECT返回的“默认”行顺序。我相信SELECT不能保证按照插入的顺序返回行。MySQL“保留权利”执行优化,最明显的例子是如果您在myID列上添加索引。我无法找到这个问题的明确答案,但在完全依赖此行为之前,您可能需要搜索“mysql select row order guarantee”。-http://sqlfiddle.com/#!2/8e316/1/0 - RandomSeed
@YaK:感谢您提醒我。在我的情况下有没有一种方法可以查找最后插入的ID呢? - Fahim Parkar
@adc:正如YaK所提到的,我的假设是错误的,因此我无法提供赏金。 - Fahim Parkar

2
似乎 SELECT 语句不保证以任何特定的顺序返回行(当然,没有使用 ORDER BY 子句时)。
根据 SQL-92 标准(第373页):

如果未指定 < order by clause >,则由 < cursor specification > 指定的表为 T,并且 T 中的行排序是实现相关的。

好吧,MySQL 不完全符合 SQL-92 标准,但这是一个重要的提示。
Laurynas Biveinis(显然与 Percona 有关)也 声明

在缺少 ORDER BY 子句的情况下,行的顺序可能因月相而异,这是可以接受的。

MySQL手册关于InnoDB的说明:

如果存在一个[主键或非空唯一索引],InnoDB总是按照该索引对表行进行排序。

就我所知,我认为MySQL甚至可以在OPTIMIZE TABLE之后重新排序行,甚至在多次删除和插入后重用空白空间(我已经试图找到一个例子,但迄今为止没有成功)。

考虑到您的表结构,不幸的是,许多因素可能改变了行的顺序。除非您自创建表以来一直保存所有二进制日志,否则我看不出有可靠地确定它们被插入的顺序的解决方案;)

尽管如此,您仍然可以向表中添加一个sequence列。现有行将被分配一个可能不准确的序列号,但至少将来的行将被正确排序。

ALTER TABLE maxID ADD sequence INT DEFAULT NULL;
ALTER TABLE maxID ADD INDEX(sequence);
ALTER TABLE maxID MODIFY sequence INT AUTO_INCREMENT;

http://sqlfiddle.com/#!2/63a8d/1


2

从你的插入脚本来看,A004并不是最后插入的记录,而是第三条。如果你想要按字母顺序获取最后一条记录(其中包括A004),你必须使用

select myID from maxID order by myID desc limit 1

如果您想获取最后插入的行,为什么不在表中添加自增列呢?这就是自增列的目的。自增列不一定是主键(虽然应该是),但如果没有其他选择,也可以不是主键。

抱歉,它没有给我想要的...注意:您正在进行排序,这是不正确的...通过排序,记录将被移动... - Fahim Parkar
请再次阅读,特别是最后一部分:您需要一个自增列,它可能不是主键。 - JB Nizet
我知道如果我添加自增列,我可以做到这一点...但是由于我已经有了表格和成千上万的数据,我不想添加额外的列并增加数据库大小...在我的情况下,我想找到最后插入的记录... - Fahim Parkar

1

MySQL关于last_insert_id的帮助中所述,你只能在**自增列上使用它。这意味着,除非你了解ID的顺序,否则无法让MySQL为你找到最近插入的行。如果它们像你的示例所示那样排序,那么你可以使用

SELECT *
FROM maxID
WHERE myId = max(myId)

但我建议在表中添加一个自动递增列,然后在您的WHERE子句中使用= last_insert_id()。有关如何获取最后一个ID的信息,请参见此页面

1
请再检查一下我的问题...我在那里得到了0的数据...我没有ID作为整数... - Fahim Parkar
我已经有了表格,而且我的ID是varchar类型,所以我现在无法更改我的表格,因为它与许多其他表格相关联... :( - Fahim Parkar
当我意识到你没有自增列时,我已经大幅更新了答案。如果你想追踪最后插入的行,你应该真的添加这样一列。 - Martin Geisler

0

last_insert_id 不起作用,因为它仅返回自动递增字段生成的最后一个值。但是我认为解决方案可能在正确的轨道上。建议添加另一列作为自动递增整数。然后,您可以插入数据并检索刚刚插入的行,选择 last_insert_id()。要检索最近的行(由任何进程插入),请选择新列的最大数,或按其进行排序。

如果要使用 varchar 列,可以进行字母排序,但无法保证它将是您插入的最后一行或甚至是最近插入的行。

我能想到的另一种解决方案是创建一个存储过程,该存储过程创建行,将其插入表中,然后将其返回给您。

您对 @rowid 的使用只是计算返回给您的行的顺序。不能保证它们以从旧到新的顺序返回给您。有许多事情可能会影响行存储的顺序。


我在我的答案中添加了一点内容。但是最重要的问题是,您是否需要刚刚输入的记录或任何给定时间点的最新记录?这个查询会立即跟随插入吗,还是可以独立完成? - Ilion
我认为根据你目前的设计,你运气不太好。既然你说不能调整当前的模式,那么你可以创建另一个表,该表使用此作为外键,并带有DateTime或自动递增ID列。这种方法相当繁琐,但它会起作用。然后,你可以在任一表上设置触发器,在接收到插入时插入到另一个表中,或通过存储过程来管理整个过程。 - Ilion
除非有myID值的顺序,并且您可以依赖它们始终按照该顺序插入,否则不行。 - Ilion
在我的问题中,我正在创建rowid作为列...使用它,问题会得到解决吗?(查找myId NewID rowid - Fahim Parkar
好的...谢谢帮忙...我会检查新表并添加自增列... - Fahim Parkar
显示剩余2条评论

-1
请使用以下查询。
Select * from maxID order by myId desc limit 1,1;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接