在Oracle中,我在存储过程的if-else
块中有以下几乎相同的SQL:
if v_endsid = '15' then
FOR i IN 1..v_num LOOP --loop around the number from the beginning
v_item := TRIM(SUBSTR(v_str, (i - 1) * 12 + 1, 12)); --now this is the evaluated item
if v_item = TRIM(cursorElement.ITEM) then --this is the time to break
break;
end if;
END LOOP;
else
FOR i IN REVERSE 1..v_num LOOP --loop around the number from the last
v_item := TRIM(SUBSTR(v_str, (i - 1) * 12 + 1, 12)); --now this is the evaluated item
if v_item = TRIM(cursorElement.ITEM) then --this is the time to break
break;
end if;
END LOOP;
end if;
如您所见,if
和else
块中的SQL之间的唯一区别是FOR
循环。一个是前向循环,另一个是反向(后向)循环。
有没有办法合并块?我正在尝试这个:
FOR i IN (case when v_endsid = '15' then 1..v_num else REVERSE 1..v_num end) LOOP
v_item := TRIM(SUBSTR(v_str, (i - 1) * 12 + 1, 12)); --now this is the evaluated item
if v_item = TRIM(cursorElement.ITEM) then --this is the time to break
break;
end if;
END LOOP;
但是它在1..v_num
:
发现:'..'期待:结束 - 或 - ELSE - 或 - 当 - 或 - 或 - 或 - 或 - 或 - 喜欢LIKE4 LIKE4 LIKEC成员亚组织 - 或 - ! !=< < =<> => > = ^ ^ =不是〜
答案 0 :(得分:1)
无法动态改变for循环的方向。如果你想要组合这两个块,你唯一能做的就是使用基本循环
if v_endsid = '15' then
i := 1;
reverse := false;
else
i := v_num;
reverse := true;
end if;
LOOP --loop around the number from the beginning
v_item := TRIM(SUBSTR(v_str, (v_num - 1) * 12 + 1, 12)); --now this is the evaluated item
if v_item = TRIM(cursorElement.ITEM) then --this is the time to break
break;
end if;
if reverse = true then
if i = 1 then
exit;
else
i := i - 1;
else
if i = v_num then
exit;
else
i := i + 1;
end if;
end if;
END LOOP;
答案 1 :(得分:1)
我适应的最终解决方案是使用基本的LOOP
和一些三元操作:
i := case when v_endsid = '15' then 1 else v_num end; --evaluates from front or back depending on the case
Loop
v_item := TRIM(SUBSTR(v_str, (i - 1) * 12 + 1, 12)); --now this is the evaluated item
--other queries
i := i + (case when v_endsid = '15' then 1 else -1 end);
exit when i = 0 or i = v_num + 1; --exceeds the elements
end loop;
我认为,这是原始SQL
的一个相当简洁的工作替代品答案 2 :(得分:0)
另一种方式怎么样?而不是操纵循环条件,将评估中断条件的代码封装到可以从不同循环中调用的函数中。
declare
v_reverse constant boolean := true;
-- your parameters and break rule can be arbitrary complex, mine is simple
-- as this is just a demonstration
function break(i in pls_integer) return boolean is
begin
return 13 = i;
end;
begin
if v_reverse
then
for i in reverse 1 .. 15
loop
dbms_output.put_line(i);
exit when break(i);
end loop;
else
for i in 1 .. 15
loop
dbms_output.put_line(i);
exit when break(i);
end loop;
end if;
end;
/