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

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

谢谢。

编辑与结论

正如贾斯汀 · 凯夫所说,试图“保存”序列号是没有用的

select a_seq.nextval from dual;

足以检查序列值。

我仍然认为奥利的回答是好的,因为它回答了最初的问题。但是问问你自己,如果你想做的话,不修改序列的必要性。

605140 次浏览
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,然后在重新设置之后返回其原始值,以确保没有缓存大量值。

select MY_SEQ_NAME.currval from DUAL;

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

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

SELECT mysequence.CURRVAL INTO v_myvariable FROM DUAL;

遗憾的是,如果您没有在您的会话中修改序列,我相信其他人正确地指出 NEXTVAL 是唯一的方法去。

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

你为什么想要它?

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

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

RonK 的问题:

select MY_SEQ_NAME.currval from DUAL;

在上面的场景中,RonK 的警告不适用,因为插入和更新将发生在同一个会话中。

我还尝试使用 CURRVAL,在我的例子中,用于查明某个进程是否向某个表插入了新行,并将该序列作为主键。我的假设是 CURRVAL 将是最快的方法。但是 a) CurrVal 不工作,它只会得到旧的值,因为您在另一个 Oracle 会话中,直到您在自己的会话中执行 NEXTVAL。而且 b) select max(PK) from TheTable也非常快,可能是因为 PK 总是被索引。或者 select count(*) from TheTable。我仍然在试验,但两个 SELECT 似乎很快。

我不介意序列中有一个间隔,但是在我的情况下,我考虑了很多轮询,我讨厌非常大的间隔的想法。特别是如果一个简单的 SELECT 也同样快的话。

结论:

  • CURRVAL 是相当无用的,因为它不检测 NEXTVAL 从另一个会话,它只返回您已经知道从您以前的 NEXTVAL
  • SELECTMAX (...) FROM... 是一个很好的解决方案,简单而快速,前提是您的序列链接到该表

常用的方法如下:

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

如果您的用例是某些后端代码插入一条记录,那么同样的代码想要检索最后的插入 id,而不指望任何底层数据访问库预置函数来做到这一点,那么,正如其他人提到的,您应该使用 SEQ_MY_NAME.NEXTVAL为您想要的列(通常是主键)编写 SQL 查询,然后从后端运行语句 SELECT SEQ_MY_NAME.CURRVAL FROM dual

请记住,CURRVAL 只有在 NEXTVAL 已被事先调用时才可调用,这在上面的策略中都是自然而然地完成的..。