【问题标题】:Get oracle sequenve next value without change it获取oracle序列下一个值而不更改它
【发布时间】:2014-01-14 21:15:12
【问题描述】:

我有一个大问题。我需要知道预言序列的下一个值而不改变它。

如果我使用 sequence.NEXTVAL ,我会得到我需要的东西。问题是值变了,所以下一条记录会得到这个值+1,对我不好。

我知道我可以使用sequence.CURRVAL,这很好,因为它不会更改值,但如果没有记录,它就不起作用,在这种情况下,序列值可以是任意数字(不仅 1 会导致序列值钢存在)。

请帮我找到解决办法。

谢谢你不一样!!!!!!

【问题讨论】:

  • “但如果没有记录,它就不起作用”是什么意思?
  • 您为什么需要知道这些?您不能将该值用于任何事情 - 在您致电 nextval 之前,其他人可能会抓住它? currval 将是未定义的,除非您在此会话中调用了 nextval;您可以查询user_sequences 视图,但这也不一定准确(其他会话、缓存、RAC...)。
  • “但是如果没有记录,它就不起作用”意味着当你没有记录和现有序列时会出错,我需要知道它以便我可以同步一些东西。
  • '我需要知道它,这样我才能同步一些东西' - 你为什么不解释(在问题中)你实际上想要实现的目标,以及你认为知道这会如何帮助?

标签: oracle sequence nextval


【解决方案1】:

您绝对不应该依赖从不丢失序列中的值,因为它们针对顺序编号的并发性进行了优化。在很多情况下,号码可能会“丢失”。

此外,dba_sequences 中可见的值可能不是实际的下一个值,因为这些数字是从内存缓存中分配的。底层序列元数据表没有关于该缓存使用情况的数据。您还应该记住,在 RAC 系统中,每个实例都有自己的序列号缓存。

您可能会描述您要解决的问题,因为序列可能不适合您。

【讨论】:

  • 我知道。你是对的,但我不做任何批评。我只想获得 NEXTVAL 值而不更改它,或者之前不使用 NEXTVAL 的 CURRVAL 值。这在 SQL 中就是这么简单!!!
  • 这样做的用例是什么?
  • 我接受了你的建议。我用了完全不同的方式。不想依赖它。谢谢大家。
【解决方案2】:

在多用户环境中没有办法。该值是已知的 - 当您调用 .NEXTVALunknown。序列不能被锁定。

【讨论】:

    【解决方案3】:

    我看不出您想知道序列的下一个值的任何原因。该值的唯一重要性是当您将其用于新记录时。因此,您要么创建一条新记录并立即返回 ID 值:

    declare
      l_id number;
    begin
       Insert into table (id) 
       values (sequence.nextval) 
       return id into l_id;
    
       -- and then do something more with the ID value
    end;
    

    或者先获取一个新ID,然后再使用

    declare   
       l_id number; 
    begin
       select sequence.nextval    
       into l_id    
       from dual;
    
        -- then do something with the ID value 
    end;
    

    【讨论】:

      【解决方案4】:

      查看“last_number”列
      select * from USER_SEQUENCES
      

      编辑:

      这仅在使用 nocache 选项创建序列时有效。

      因此,如果序列确实有缓存设置,请将其删除并使用 nocache 重新创建,然后您可以使用 user_sequences.last_number +1。

      请注意,如果序列被大量使用,则会影响性能。反过来说,如果序列用得不多,那就没问题了。

      短写应用程序(这是最好的解决方案),这只是解决方案。

      【讨论】:

      • 谢谢,但它与 NEXTVAL 的值不同。
      • 我不明白 currval 的问题。听起来你在说如果 seq 还没有价值,那么它会出错吗?发生这种情况时,您可以假设该值为 0 吗?或者检查 user_sequences 并查看值为 0? user_sequences 也有一列“cache_size”,我的帮助引导了 nextval。 (我不知道……需要在 RAC 环境中过期。)
      • 啊……我现在明白了…… currval 直到 nextval 被击中才被定义。您只能将下一个 val 近似为:last_number-cache_size+1 参见 asktom.oracle.com/pls/asktom/…
      【解决方案5】:

      嗯,我能给你的唯一建议是获取 nextval 然后恢复。但注意:仅当您的序列未从任何其他会话开始使用时,才执行这些操作。否则,如果在此操作期间从另一个会话中获取序列,则您可能永远无法恢复到原始值。因此在检查之前要小心:

      在我的数据库中,seq_test 的当前值为 6

      --获取下一个值

      SQL> SELECT seq_test.NEXTVAL FROM dual;
      
         NEXTVAL
      ----------
               7
      

      -- 好的,这是下一个值,现在恢复为原始值

      SQL> ALTER SEQUENCE seq_test INCREMENT BY -1;
      
      Sequence altered.
      
      SQL> SELECT seq_test.NEXTVAL FROM dual;
      
         NEXTVAL
      ----------
               6
      

      -- 按子句恢复原增量

      SQL> ALTER SEQUENCE seq_test INCREMENT BY 1;
      
      Sequence altered.
      

      --检查

      SQL> SELECT seq_test.CURRVAL FROM dual;
      
         CURRVAL
      ----------
               6
      

      我再次警告你,这可能是致命的 ;-)

      【讨论】:

      • 您肯定需要使用锁定机制,例如 DBMS_Lock,因此将其作为一个实用的系统,并且需要将其包含在对序列 nextval 的每次调用中。
      猜你喜欢
      • 2019-02-18
      • 2011-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-08
      相关资源
      最近更新 更多