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


156

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

谢谢。

编辑与结论

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

select a_seq.nextval from dual;

足以检查序列值。

我仍然保持Ollie的回答为好答案,因为它回答了最初的问题。但请问一下自己是否有必要修改序列的必要性。


5
为什么?您要解决的问题是什么?如果正确使用了序列,则永远不要在乎将哪些序列值分配给其他会话,或者将哪些值分配给后续会话。
贾斯汀·凯夫

3
数据迁移后进行检查,以确保已根据迁移的数据正确更新了序列
frno 2012年

3
那么,简单地获取nextval要测试的序列的不利之处是什么?您不是在假设序列是无间隙的,对吗?因此,“浪费”序列值不应该成为问题。
贾斯汀·凯夫

我猜你是对的,我不想更改该检查的数据库状态,但是说实话我不知道为什么。感谢您的见解。不过,我确实了解了您有关顺序的知识,谢谢大家!
frno 2012年

假设您可以可靠地获取序列的值,那么正在检查序列是否已正确更新的oracle是什么?
Shannon Severance 2012年

Answers:


173
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重置之前的值,然后再重置为原始值,以确保没有缓存很多值。


刚刚尝试过,但我无法访问“ all_sequences”表。您是否只有管理员凭据才能看到一个特殊的对象?
frno 2012年

1
ALL_SEQUENCES是一个视图。如果您无权访问,请尝试从USER_SEQUENCES默认模式中选择序列。(您不需要的sequence_owner = '<sequence_owner>'子句USER_SEQUENCES)。
Ollie 2012年

15
LAST_NUMBERALL_SEQUENCES不会是最后一个号码,一个会话实际提供并不会会从调用返回的数量sequence_name.nextval一般。假设您已将序列设置为CACHE大于1(默认值为20),LAST_NUMBER它将是缓存中的最后一个数字。无法保证将这个数字实际分配给任何会话。
贾斯汀·凯夫

2
ALTER SEQUENCE seq INCREMENT BY -1;除非可以保证没有其他会话会调用,否则这将是一个问题seq.nextval。否则,序列将分发重复的值,这通常不是人们想要的。
Shannon Severance 2012年

1
OP确实说过“这是对数据迁移后的检查”,因此假定数据库不被普遍使用并不是一件容易的事,但是如果不是这样的话,这可能是一个问题。
Ollie

122

select MY_SEQ_NAME.currval from DUAL;

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


1
非常感谢您的回答。我必须在Boomi内部使用此功能,并在上下寻求解决方案
学习...

0

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

SELECT mysequence.CURRVAL INTO v_myvariable FROM DUAL;

可悲的是,如果您没有在会话中修改序列,我相信其他人都正确地说NEXTVAL是唯一的方法。


0

这不是答案,实际上,如果问题未锁定,我将其作为评论输入。这回答了这个问题:

你为什么要呢?

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

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

RonK的查询:

select MY_SEQ_NAME.currval from DUAL;

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


0

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

我不介意序列中存在差距,但就我而言,我正在考虑进行大量轮询,并且我讨厌存在很大差距的想法。尤其是如果简单的SELECT速度一样快。

结论:

  • CURRVAL几乎没有用,因为它没有从另一个会话中检测到NEXTVAL,它仅返回您从先前的NEXTVAL中已经知道的内容
  • SELECT MAX(...)FROM ...是一个很好的解决方案,简单快速,假设您的序列已链接到该表
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.