【问题标题】:incrementing i with condition增加 i 条件
【发布时间】:2021-05-12 05:32:01
【问题描述】:

每当 v_id 的值不同时,我想将 i 加 1。

    i = 1;
   
    for i in 1..10 loop 
      SELECT subject_details.NEXTVAL 
        INTO v_id 
        FROM dual;
    
      INSERT INTO employee (id, subject) 
           VALUES (i,v_id);

      i = i + 1;
    end loop;

这是做什么的

  id subject
    1  3647
    2  3647
    3  5678
    4  5678
    5  5678

但我想要的是每当“v_id”的值发生变化时将“i”的值增加 1

id subject
1  3647
1  3647
2  5678
2  5678
2  5678

【问题讨论】:

  • 那么i = v_id - 999 ?
  • 这里的 v_id 值只是一个例子。也可以是 74685 或 36495
  • 我很想知道调用 sequence.nextval 如何在连续迭代中返回相同的值
  • 离题:为什么是SELECT subject_details.NEXTVAL INTO v_id FROM dual; 而不是v_id := subject_details.nextval
  • 我会放弃循环并考虑采用 Gordon 的 dense_rank 想法并在 insert into .... select ... 语句中使用它。您可能还在循环游标,这会很慢。当您可以进行基于集合的处理(例如单个 SQL 语句)时,不要进行逐行处理(例如循环游标)

标签: sql oracle for-loop plsql increment


【解决方案1】:

虽然提供了很好的建议,但我认为他们大多忽略了你最大的错误。我相信这是对 pl/sql 作用域规则的误解。在游览代码的某个地方(在您发布之前),您定义了一个变量 i 然后创建 i 作为 FOR 循环的索引变量。您面临的问题是,由于范围规则这些不是同一个变量。根据documentation:(另见demonstration here

for index name
隐式声明的整数变量的名称,即 FOR LOOP 语句的局部变量。循环外的语句不能 参考指数。循环内的语句可以引用索引,但是 不能改变它的值。 FOR LOOP 语句运行后,索引为 未定义。

您的流程还有一些其他问题:

  • 在 Oracle 中,赋值运算符是 := 而不是 =; (我假设这只是 一个错字)。
  • 在每次循环迭代中运行“subject_details.NEXTVAL”,然后 随后将该结果插入到您的表中。这样做会 每次增加值。因此你不能生产你想要的 输出 - 也不是您声称的输出。

【讨论】:

    【解决方案2】:

    我认为你可以使用dense_rank():

    select t.*, dense_rank() over (order by subject) 
    from t;
    

    如果值可以交错,那么您可以使用lag() 和累积和:

    select t.*,
           sum(case when prev_subject = subject then 0 else 1 end) over (order by id)
    from (select t.*,
                 lag(subject) over (order by id) as prev_subject
          from t
         ) t;
    

    【讨论】:

    • 但我希望将这些值插入表中。可以在insert语句中使用dense_Rank吗?
    • @newintodev 。 . .是的。任何select 语句都适用于insert
    【解决方案3】:

    试试

    j = 1;
    v_id_copy = 0;
    for i in 1..10 loop 
    SELECT subject_details.NEXTVAL INTO v_id FROM dual;
    if(v_id_copy==0) then
    v_id_copy = v_id;
    elseif (v_id_copy != v_id) then
    j=j+1;
    v_copy_id=v_id;
    endif
    insert into employee (id,subject) values (j,v_id)
    end loop;
    

    【讨论】:

    • 您好 Zakaria,欢迎来到 Stack Overflow。虽然您的代码可以回答问题,但您可以通过提供上下文来改进它:如何/为什么解决问题?你所做的与有效的提问者有什么不同?
    猜你喜欢
    • 2011-10-06
    • 1970-01-01
    • 2014-02-22
    • 2022-07-20
    • 1970-01-01
    • 2020-11-25
    • 1970-01-01
    • 1970-01-01
    • 2017-08-11
    相关资源
    最近更新 更多