Oracle序列nextval和currval令人困惑

Nig*_*ade 15 oracle plsql

在我的程序中,我写这个

INSERT INTO questions(id, value) VALUES(my_seq.NEXTVAL, p_question);

INSERT INTO DEPENDENCIES(parent_question_id, child_question_id)
VALUES (my_seq.CURRVAL, my_seq.NEXTVAL);
Run Code Online (Sandbox Code Playgroud)

假设序列的最后一个值等于1.在这种情况下,我期望这个结果:

 my_seq.NEXTVAL = 2;
 my_seq.CURRVAL = 2;
 my_seq.NEXTVAL = 3;
Run Code Online (Sandbox Code Playgroud)

但它插入了这个:

 my_seq.NEXTVAL = 2;
 my_seq.CURRVAL = 3;
 my_seq.NEXTVAL = 3;
Run Code Online (Sandbox Code Playgroud)

我想知道为什么oracle以这种方式检索序列值?

Chr*_*mer 14

如果你有三个单独的陈述:

  1. NEXTVAL

  2. CURRVAL

  3. NEXTVAL

那你就是对的.但你只有两个

  1. NEXTVAL

  2. currval和nextval

Currval和nextval是单个原子步骤的一部分 - 在nextval之前不会处理currval.

您需要为此使用变量:

DECLARE
  l_parent_question_id     NUMBER ;
  l_child_question_id      NUMBER ;
BEGIN
  l_parent_question_id := my_seq.NEXTVAL ;

  INSERT INTO questions(id, value) VALUES(l_parent_question_id, p_question);

  l_child_question_id := my_seq.NEXTVAL ;

  INSERT INTO DEPENDENCIES(parent_question_id, child_question_id)
  VALUES (l_parent_question_id, l_child_question_id); 

END ;
Run Code Online (Sandbox Code Playgroud)

  • 我肯定会避免使用currval-1构造.它确实有效(因为CURRVAL只返回会话的值 - 不存在不同会话会影响该值的危险)但请考虑一下在两年内必须更新代码的糟糕开发人员.除非你发表评论,否则他们不会知道你的意图.但是通过使用变量,你真正清楚自己要做什么 - 代码注释本身 (5认同)
  • @ChristianPalmer - 是的,但在这种情况下(OP的评论)它与同一语句中的`nextval`相同(正如你的答案所解释的).所以在这个会话中第一次插入的`nextval`得到42; 一些其他会话增加序列; 在这个会话的第二个插入中的`nextval`然后得到44.在那个语句中`currval`现在也是44,所以`currval-1`是43 - 不是预期/期望的42.是的,我们同意它是不是一个好主意,我只是补充说它比你的评论建议的更糟糕*8-) (2认同)