Oracle PL/SQL变量中的循环不是游标

Oracle PL/SQL变量中的循环不是游标,oracle,plsql,Oracle,Plsql,我正在尝试运行以下循环: DECLARE v_banknumber varchar2(9) := '123456789'; v_counter number := 9; v_result number; begin for i in v_banknumber loop v_result := v_counter * TO_NUMBER(i) + v_result; v_counter := v_counter - 1; end loop; end; 我在第2行遇到一个错误

我正在尝试运行以下循环:

DECLARE
v_banknumber varchar2(9) := '123456789';
v_counter number := 9;
v_result number;
begin
for i in v_banknumber 
loop
    v_result := v_counter * TO_NUMBER(i) + v_result;
    v_counter := v_counter - 1;
 end loop;
 end;
我在第2行遇到一个错误:

Error report -
ORA-06550: line 6, column 10:
PLS-00456: item 'V_BANKNUMBER' is not a cursor
ORA-06550: line 6, column 1:
PL/SQL: Statement ignored
06550. 00000 -  "line %s, column %s:\n%s"
*Cause:    Usually a PL/SQL compilation error.
*Action:
如果我读得好的话,它似乎应该会起作用。这里有人能解释为什么它不起作用吗


第一个数字必须乘以9,第二个数字必须乘以8,第三个数字必须乘以7,依此类推,并将其总和保存在结果变量中。

猜测一下,您要做的是

DECLARE
  v_banknumber varchar2(9) := '123456789';
  v_counter number := 9;
  v_result number := 0;
begin
  for i in 1..LENGTH(v_banknumber)
  loop
    v_result := v_counter * TO_NUMBER(SUBSTR(v_banknumber, i, 1)) + v_result;
    v_counter := v_counter - 1;
   end loop;
 end;
这给出了165的结果

祝你好运

编辑 或者你可以使用光标:

DECLARE
  v_banknumber varchar2(9) := '123456789';
  v_counter number := 9;
  v_result number := 0;
begin
  for aRow in (SELECT LEVEL AS I FROM DUAL CONNECT BY LEVEL <= LENGTH(v_banknumber)) 
  loop
    v_result := v_counter * TO_NUMBER(SUBSTR(v_banknumber, aRow.I, 1)) + v_result;
    v_counter := v_counter - 1;
   end loop;
 end;
结果生成165

编辑2 或者,因为没有比overkill更好的杀戮,所以您可以在SQL中完成这一切:

WITH cteBank_number AS (SELECT '123456789' AS BANK_NUMBER FROM DUAL),
     cteI AS (SELECT LEVEL AS I
                FROM DUAL d
                CROSS JOIN cteBank_number b
                CONNECT BY LEVEL <= LENGTH(b.BANK_NUMBER)),
     cteNums AS (SELECT TO_NUMBER(SUBSTR(b.BANK_NUMBER, LENGTH(b.BANK_NUMBER)-i.I+1, 1)) AS DIGIT,
                        i.I AS I,
                        TO_NUMBER(SUBSTR(b.BANK_NUMBER, LENGTH(b.BANK_NUMBER)-i.I+1, 1)) * i.I AS NUM
                   FROM cteBank_number b
                   CROSS JOIN cteI i)
SELECT SUM(NUM)
  FROM cteNums n;

仍然会产生165个结果。

猜测一下,您要做的是

DECLARE
  v_banknumber varchar2(9) := '123456789';
  v_counter number := 9;
  v_result number := 0;
begin
  for i in 1..LENGTH(v_banknumber)
  loop
    v_result := v_counter * TO_NUMBER(SUBSTR(v_banknumber, i, 1)) + v_result;
    v_counter := v_counter - 1;
   end loop;
 end;
这给出了165的结果

祝你好运

编辑 或者你可以使用光标:

DECLARE
  v_banknumber varchar2(9) := '123456789';
  v_counter number := 9;
  v_result number := 0;
begin
  for aRow in (SELECT LEVEL AS I FROM DUAL CONNECT BY LEVEL <= LENGTH(v_banknumber)) 
  loop
    v_result := v_counter * TO_NUMBER(SUBSTR(v_banknumber, aRow.I, 1)) + v_result;
    v_counter := v_counter - 1;
   end loop;
 end;
结果生成165

编辑2 或者,因为没有比overkill更好的杀戮,所以您可以在SQL中完成这一切:

WITH cteBank_number AS (SELECT '123456789' AS BANK_NUMBER FROM DUAL),
     cteI AS (SELECT LEVEL AS I
                FROM DUAL d
                CROSS JOIN cteBank_number b
                CONNECT BY LEVEL <= LENGTH(b.BANK_NUMBER)),
     cteNums AS (SELECT TO_NUMBER(SUBSTR(b.BANK_NUMBER, LENGTH(b.BANK_NUMBER)-i.I+1, 1)) AS DIGIT,
                        i.I AS I,
                        TO_NUMBER(SUBSTR(b.BANK_NUMBER, LENGTH(b.BANK_NUMBER)-i.I+1, 1)) * i.I AS NUM
                   FROM cteBank_number b
                   CROSS JOIN cteI i)
SELECT SUM(NUM)
  FROM cteNums n;
仍然生成165作为结果。

您的v_banknumber变量是字符串而不是光标。您需要循环该字符串中的每个字符,并将该字符视为一个数字

您可以这样做:

 set serveroutput on

declare
  v_banknumber varchar2(9) := '123456789';
  v_result number := 0;
begin
  for v_counter in reverse 1..length(v_banknumber)
  loop
    v_result := v_result
      + (v_counter * to_number(substr(v_banknumber, -v_counter, 1)));
  end loop;

  dbms_output.put_line('The result is: ' || v_result);
end;
/

The result is: 165

PL/SQL procedure successfully completed.
通过额外的调试,尝试显示每次迭代中发生的情况:

declare
  v_banknumber varchar2(9) := '123456789';
  v_result number := 0;
begin
  dbms_output.put_line('length(v_banknumber) is: ' || length(v_banknumber));
  for v_counter in reverse 1..length(v_banknumber)
  loop
    dbms_output.put_line('v_counter is: ' || v_counter);
    dbms_output.put_line('  Digit is substr(v_banknumber, v_counter, 1): '
      || substr(v_banknumber, -v_counter, 1));
    dbms_output.put_line('  Calculation for digit is: '
      || v_counter * to_number(substr(v_banknumber, -v_counter, 1)));
    v_result := v_result
      + (v_counter * to_number(substr(v_banknumber, -v_counter, 1)));
    dbms_output.put_line('  Running total: ' || v_result);
  end loop;

  dbms_output.put_line('The result is: ' || v_result);
end;
/

length(v_banknumber) is: 9
v_counter is: 9
  Digit is substr(v_banknumber, v_counter, 1): 1
  Calculation for digit is: 9
  Running total: 9
v_counter is: 8
  Digit is substr(v_banknumber, v_counter, 1): 2
  Calculation for digit is: 16
  Running total: 25
v_counter is: 7
  Digit is substr(v_banknumber, v_counter, 1): 3
  Calculation for digit is: 21
  Running total: 46
v_counter is: 6
  Digit is substr(v_banknumber, v_counter, 1): 4
  Calculation for digit is: 24
  Running total: 70
v_counter is: 5
  Digit is substr(v_banknumber, v_counter, 1): 5
  Calculation for digit is: 25
  Running total: 95
v_counter is: 4
  Digit is substr(v_banknumber, v_counter, 1): 6
  Calculation for digit is: 24
  Running total: 119
v_counter is: 3
  Digit is substr(v_banknumber, v_counter, 1): 7
  Calculation for digit is: 21
  Running total: 140
v_counter is: 2
  Digit is substr(v_banknumber, v_counter, 1): 8
  Calculation for digit is: 16
  Running total: 156
v_counter is: 1
  Digit is substr(v_banknumber, v_counter, 1): 9
  Calculation for digit is: 9
  Running total: 165
The result is: 165
您的v_banknumber变量是一个字符串而不是光标。您需要循环该字符串中的每个字符,并将该字符视为一个数字

您可以这样做:

 set serveroutput on

declare
  v_banknumber varchar2(9) := '123456789';
  v_result number := 0;
begin
  for v_counter in reverse 1..length(v_banknumber)
  loop
    v_result := v_result
      + (v_counter * to_number(substr(v_banknumber, -v_counter, 1)));
  end loop;

  dbms_output.put_line('The result is: ' || v_result);
end;
/

The result is: 165

PL/SQL procedure successfully completed.
通过额外的调试,尝试显示每次迭代中发生的情况:

declare
  v_banknumber varchar2(9) := '123456789';
  v_result number := 0;
begin
  dbms_output.put_line('length(v_banknumber) is: ' || length(v_banknumber));
  for v_counter in reverse 1..length(v_banknumber)
  loop
    dbms_output.put_line('v_counter is: ' || v_counter);
    dbms_output.put_line('  Digit is substr(v_banknumber, v_counter, 1): '
      || substr(v_banknumber, -v_counter, 1));
    dbms_output.put_line('  Calculation for digit is: '
      || v_counter * to_number(substr(v_banknumber, -v_counter, 1)));
    v_result := v_result
      + (v_counter * to_number(substr(v_banknumber, -v_counter, 1)));
    dbms_output.put_line('  Running total: ' || v_result);
  end loop;

  dbms_output.put_line('The result is: ' || v_result);
end;
/

length(v_banknumber) is: 9
v_counter is: 9
  Digit is substr(v_banknumber, v_counter, 1): 1
  Calculation for digit is: 9
  Running total: 9
v_counter is: 8
  Digit is substr(v_banknumber, v_counter, 1): 2
  Calculation for digit is: 16
  Running total: 25
v_counter is: 7
  Digit is substr(v_banknumber, v_counter, 1): 3
  Calculation for digit is: 21
  Running total: 46
v_counter is: 6
  Digit is substr(v_banknumber, v_counter, 1): 4
  Calculation for digit is: 24
  Running total: 70
v_counter is: 5
  Digit is substr(v_banknumber, v_counter, 1): 5
  Calculation for digit is: 25
  Running total: 95
v_counter is: 4
  Digit is substr(v_banknumber, v_counter, 1): 6
  Calculation for digit is: 24
  Running total: 119
v_counter is: 3
  Digit is substr(v_banknumber, v_counter, 1): 7
  Calculation for digit is: 21
  Running total: 140
v_counter is: 2
  Digit is substr(v_banknumber, v_counter, 1): 8
  Calculation for digit is: 16
  Running total: 156
v_counter is: 1
  Digit is substr(v_banknumber, v_counter, 1): 9
  Calculation for digit is: 9
  Running total: 165
The result is: 165

你是想把它当作一个数组吗

DECLARE
  type array_t is varray(9) of number;
  a_banknumber array_t := array_t (1,2,3,4,5,6,7,8,9);
  v_counter number := a_banknumber.count;
  v_result number := 0;
begin

  for i in 1..a_banknumber.count  
  loop
    v_result := v_counter * a_banknumber(i) + v_result;
    v_counter := v_counter - 1;
  end loop;
  dbms_output.put_line('Result: ' || v_result);
end;

你是想把它当作一个数组吗

DECLARE
  type array_t is varray(9) of number;
  a_banknumber array_t := array_t (1,2,3,4,5,6,7,8,9);
  v_counter number := a_banknumber.count;
  v_result number := 0;
begin

  for i in 1..a_banknumber.count  
  loop
    v_result := v_counter * a_banknumber(i) + v_result;
    v_counter := v_counter - 1;
  end loop;
  dbms_output.put_line('Result: ' || v_result);
end;

谢谢你,鲍勃!我真的很感激你的回答。这正是我要找的。谢谢你,鲍勃!我真的很感激你的回答。这正是我要找的。不,我不是想把它作为一个数组。但谢谢你,我从前人那里得到了正确的答案。这只是解决问题的另一种方法-不,我不是想把它当作一个数组。但谢谢你,我从前人那里得到了正确的答案。这只是解决问题的另一种方法-