提问人:frno 提问时间:4/18/2012 最后编辑:wolφifrno 更新时间:4/20/2023 访问量:668555
如何在不递增的情况下检索预言机序列的当前值?
How to retrieve the current value of an oracle sequence without increment it?
问:
是否有 SQL 指令来检索不递增序列的值。
谢谢。
编辑和结论
正如贾斯汀·凯夫(Justin Cave)所说,尝试“保存”序列号是没有用的,所以
select a_seq.nextval from dual;
足以检查序列值。
我仍然认为 Ollie 的答案是好的,因为它回答了最初的问题。但是,如果您想这样做,请问问自己是否有必要不修改序列。
答:
SELECT last_number
FROM all_sequences
WHERE sequence_owner = '<sequence owner>'
AND sequence_name = '<sequence_name>';
您可以从 和 中获取各种序列元数据。user_sequences
all_sequences
dba_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
是一个视图。如果您无权访问它,请尝试从序列是否在默认架构中进行选择。(您不需要 的子句 )。USER_SEQUENCES
sequence_owner = '<sequence_owner>'
USER_SEQUENCES
LAST_NUMBER
ALL_SEQUENCES
sequence_name.nextval
CACHE
LAST_NUMBER
ALTER SEQUENCE seq INCREMENT BY -1;
这将是一个问题,除非可以保证没有其他会话会调用 .否则,序列将分发重复值,这通常不是人们想要的。seq.nextval
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) a 也非常快,可能是因为 PK 总是被索引。或。我仍在尝试,但两个 SELECT 似乎都很快。select max(PK) from TheTable
select count(*) from TheTable
我不介意序列中的间隙,但就我而言,我正在考虑进行大量轮询,我讨厌非常大的间隙的想法。特别是如果一个简单的 SELECT 同样快。
结论:
- CURRVAL 非常无用,因为它不会从另一个会话中检测到 NEXTVAL,它只返回您从以前的 NEXTVAL 中已经知道的内容
- 选择 MAX(...)从。。。是一个很好的解决方案,简单快捷,假设您的序列链接到该表
经常使用以下内容:
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,而不指望任何底层数据访问库预设函数来执行此操作,那么,正如其他人所提到的,你应该只使用你想要的列(通常是主键)来制作你的 SQL 查询, 然后从后端运行语句。SEQ_MY_NAME.NEXTVAL
SELECT SEQ_MY_NAME.CURRVAL FROM dual
请记住,CURRVAL 只有在 NEXTVAL 被预先调用的情况下才可调用,这在上面的策略中都是自然而然的......
评论
我们可以使用下面的查询来获取序列下一个值。
select last_number from dba_sequences where sequence_name = '<sequence name>';
评论
nextval