如何在不递增的情况下检索预言机序列的当前值?

How to retrieve the current value of an oracle sequence without increment it?

提问人:frno 提问时间:4/18/2012 最后编辑:wolφifrno 更新时间:4/20/2023 访问量:668555

问:

是否有 SQL 指令来检索不递增序列的值。

谢谢。

编辑和结论

正如贾斯汀·凯夫(Justin Cave)所说,尝试“保存”序列号是没有用的,所以

select a_seq.nextval from dual;

足以检查序列值。

我仍然认为 Ollie 的答案是好的,因为它回答了最初的问题。但是,如果您想这样做,请问问自己是否有必要不修改序列。

SQL Oracle 序列

评论

7赞 Justin Cave 4/18/2012
为什么?您要解决的问题是什么?如果正确使用序列,则永远不用关心哪些序列值已分配给其他会话,或者哪些值可能分配给后续会话。
4赞 frno 4/18/2012
这是数据迁移后的检查,以确保序列已根据迁移的数据正确更新
5赞 Justin Cave 4/18/2012
那么,简单地让序列进行测试有什么缺点呢?你不会假设序列是无间隙的,对吧?因此,“浪费”序列值应该不是问题。nextval
0赞 frno 4/18/2012
我想你是对的,我不想更改该检查的数据库状态,但老实说,我不知道为什么。感谢您的见解。尽管如此,我确实学到了你关于序列的东西,谢谢大家!
1赞 Nathan Goings 6/14/2020
@JustinCave,有一个我正在执行数据迁移的系统,我不知道是否需要无间隙。尽可能少的副作用可以防止我和未来的人追逐解决其他问题的红鲱鱼。

答:

207赞 Ollie 4/18/2012 #1
SELECT last_number
  FROM all_sequences
 WHERE sequence_owner = '<sequence owner>'
   AND sequence_name = '<sequence_name>';

您可以从 和 中获取各种序列元数据。user_sequencesall_sequencesdba_sequences

这些视图适用于多个会话。

编辑:

如果序列位于默认架构中,则:

SELECT last_number
  FROM user_sequences
 WHERE sequence_name = '<sequence_name>';

如果您想要所有元数据,那么:

SELECT *
  FROM user_sequences
 WHERE sequence_name = '<sequence_name>';

编辑2:

如果您的缓存大小不是 1,则更可靠的方法如下:

SELECT increment_by I
  FROM user_sequences
 WHERE sequence_name = 'SEQ';

      I
-------
      1

SELECT seq.nextval S
  FROM dual;

      S
-------
   1234

-- Set the sequence to decrement by 
-- the same as its original increment
ALTER SEQUENCE seq 
INCREMENT BY -1;

Sequence altered.

SELECT seq.nextval S
  FROM dual;

      S
-------
   1233

-- Reset the sequence to its original increment
ALTER SEQUENCE seq 
INCREMENT BY 1;

Sequence altered.

请注意,如果其他人在此期间使用该序列 - 他们(或您)可能会得到

ORA-08004: sequence SEQ.NEXTVAL goes below the sequences MINVALUE and cannot be instantiated

此外,您可能希望在重置之前将缓存设置为,然后在重置后恢复其原始值,以确保没有缓存大量值。NOCACHE

评论

0赞 frno 4/18/2012
刚刚尝试过,但我无法访问“all_sequences”表。它是您只能通过管理员凭据看到的特殊对象吗?
1赞 Ollie 4/18/2012
ALL_SEQUENCES是一个视图。如果您无权访问它,请尝试从序列是否在默认架构中进行选择。(您不需要 的子句 )。USER_SEQUENCESsequence_owner = '<sequence_owner>'USER_SEQUENCES
18赞 Justin Cave 4/18/2012
in 不会是实际给出会话的最后一个号码,也不会是通常从呼叫返回的号码。假设您已将序列设置为大于 1(默认值为 20),则将是缓存中的最后一个数字。不能保证这个号码会真正提供给任何会话。LAST_NUMBERALL_SEQUENCESsequence_name.nextvalCACHELAST_NUMBER
3赞 Shannon Severance 4/19/2012
ALTER SEQUENCE seq INCREMENT BY -1;这将是一个问题,除非可以保证没有其他会话会调用 .否则,序列将分发重复值,这通常不是人们想要的。seq.nextval
2赞 Ollie 4/19/2012
OP 确实说过“这是数据迁移后的检查”,因此假设数据库不在一般使用并不夸张,但如果不是这种情况,这可能是一个问题。
151赞 RonK 4/18/2012 #2

select MY_SEQ_NAME.currval from DUAL;

请记住,它仅在您在当前会话中运行时才有效。select MY_SEQ_NAME.nextval from DUAL;

评论

1赞 learning... 1/22/2020
非常感谢您的回答。我必须在 Boomi 中使用它,并且一直在上下寻找解决方案
-2赞 georgejo 9/13/2017 #3

我最初的回复实际上是不正确的,我很高兴它被删除了。下面的代码将在以下条件下工作:a) 您知道没有其他人修改了序列 b) 您的会话修改了该序列。就我而言,我遇到了一个类似的问题,我调用了一个修改值的过程,我相信这个假设是正确的。

SELECT mysequence.CURRVAL INTO v_myvariable FROM DUAL;

可悲的是,如果您没有修改会话中的顺序,我相信其他人说 NEXTVAL 是唯一的出路是正确的。

2赞 Ainsworth 3/29/2019 #4

这不是一个答案,真的,如果问题没有被锁定,我会把它作为评论输入。这回答了以下问题:

你为什么想要它?

假设您有一个以序列为主键的表,并且该序列由插入触发器生成。如果希望序列可用于记录的后续更新,则需要有一种方法来提取该值。

为了确保您得到正确的查询,您可能希望将 INSERT 和 RonK 的查询包装在事务中。

RonK 的查询:

select MY_SEQ_NAME.currval from DUAL;

在上述情况下,RonK 的警告不适用,因为插入和更新将在同一会话中发生。

1赞 Roland 8/15/2019 #5

我还尝试使用 CURRVAL,在我的情况下,以确定某些进程是否将新行插入到某个表中,并将该序列作为主键。我的假设是 CURRVAL 将是最快的方法。但是 a) CurrVal 不起作用,它只会获得旧值,因为您在另一个 Oracle 会话中,直到您在自己的会话中执行 NEXTVAL。b) a 也非常快,可能是因为 PK 总是被索引。或。我仍在尝试,但两个 SELECT 似乎都很快。select max(PK) from TheTableselect count(*) from TheTable

我不介意序列中的间隙,但就我而言,我正在考虑进行大量轮询,我讨厌非常大的间隙的想法。特别是如果一个简单的 SELECT 同样快。

结论:

  • CURRVAL 非常无用,因为它不会从另一个会话中检测到 NEXTVAL,它只返回您从以前的 NEXTVAL 中已经知道的内容
  • 选择 MAX(...)从。。。是一个很好的解决方案,简单快捷,假设您的序列链接到该表
9赞 caot 9/17/2020 #6

经常使用以下内容:

select field_SQ.nextval from dual;  -- it will increase the value by 1 for each run
select field_SQ.currval from DUAL;

但是,以下操作能够将序列更改为预期的顺序。可以是整数(负数或正数)1

alter sequence field_SQ increment by 1 minvalue 0

评论

0赞 Cezary Butler 3/26/2022
这是我记得的,但它不起作用。
1赞 Fabien Haddadi 10/22/2020 #7

如果你的用例是某个后端代码插入了一条记录,那么同样的代码想要检索最后一个插入 ID,而不指望任何底层数据访问库预设函数来执行此操作,那么,正如其他人所提到的,你应该只使用你想要的列(通常是主键)来制作你的 SQL 查询, 然后从后端运行语句。SEQ_MY_NAME.NEXTVALSELECT SEQ_MY_NAME.CURRVAL FROM dual

请记住,CURRVAL 只有在 NEXTVAL 被预先调用的情况下才可调用,这在上面的策略中都是自然而然的......

评论

0赞 Fabien Haddadi 11/14/2020
嗯,这适用于我的用例。因此,无论谁对我投了反对票,都应该用正当的理由详细说明他们的行动......
0赞 Chamith 4/20/2023 #8

我们可以使用下面的查询来获取序列下一个值。

select last_number from dba_sequences where sequence_name = '<sequence name>';