oracle 一旦用户在PL/SQL中输入负数,就无法显示最终输出

lnxxn5zx  于 2022-11-03  发布在  Oracle
关注(0)|答案(2)|浏览(372)

一旦用户输入了负数,我就无法显示最终输出。
我试着创建一个程序,它会不断地询问用户输入数字。如果用户输入一个负数,程序将停止运行,并显示总数、平均数、输入的零的个数、最大值和最小值。下面是我编写的代码:

SET SERVEROUTPUT ON;

DECLARE
    n NUMBER(3);
    total NUMBER(3) := 0;
    numZeros NUMBER(3) := 0;
    average NUMBER(3);
    highest NUMBER(3) := 0;
    lowest NUMBER(3) := 0;
BEGIN
    LOOP
        n := &n;
        total := total + n;
        IF n = 0 THEN
           numZeros := numZeros + 1;
        ELSIF n > highest THEN
            high := n;
        ELSIF n < lowest THEN
            low := n;
        END IF;
        EXIT WHEN n < 0;
    END LOOP;
    average := total / n;
    DBMS_OUTPUT.PUT_LINE('Total: ' || total);
    DBMS_OUTPUT.PUT_LINE('Average: ' || average);
    DBMS_OUTPUT.PUT_LINE('Number of zeros: ' || numZeros);
    DBMS_OUTPUT.PUT_LINE('Highest number: ' || highest);
    DBMS_OUTPUT.PUT_LINE('Lowest number: ' || lowest);
END;

输出抛出了一个错误,说“N”不是一个过程。我希望能得到一些帮助来解决这个问题。

2hh7jdfx

2hh7jdfx1#

您的代码存在一个基本问题,&amp;是一个替代变量,由客户端应用程序(即SQL*Plus、SQL Developer或其他支持替代变量的客户端,但并非所有Oracle客户端都支持替代变量)进行求值,并且在实际实施时就像对源代码执行了查找-替换操作一样。
一旦从属端取代了替代变数,叙述句就会传送至PL/SQL引擎将剖析它的数据库。PL/SQL引擎永远不会看到替代变数(因为它是由从属端应用程序行程的),即使看到了,也不会了解如何行程它。
这意味着系统将提示您输入替换ONCE(且仅提示一次),然后在每次循环迭代中使用该值,这样,如果您先输入一个正数,则循环将永远不退出;如果您先输入一个负数,则循环将立即退出。
如果要输入值列表,则需要一次输入所有值:

SET SERVEROUTPUT ON;

DECLARE
  items    SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST(0,1,2,3,4,5);

  total    NUMBER(3,0) := 0;
  numZeros NUMBER(3,0) := 0;
  average  NUMBER(5,2) := NULL;
  highest  NUMBER(3,0) := NULL;
  lowest   NUMBER(3,0) := NULL;
BEGIN
  FOR i IN 1 .. items.COUNT LOOP
    total := total + items(i);
    IF items(i) = 0 THEN
      numZeros := numZeros + 1;
    END IF;
    IF highest IS NULL OR items(i) > highest THEN
      highest := items(i);
    END IF;
    IF lowest IS NULL OR items(i) < lowest THEN
      lowest := items(i);
    END IF;
  END LOOP;
  IF items.COUNT > 0 THEN
    average := total / items.COUNT;
  END IF;

  DBMS_OUTPUT.PUT_LINE('Total: ' || total);
  DBMS_OUTPUT.PUT_LINE('Average: ' || average);
  DBMS_OUTPUT.PUT_LINE('Number of zeros: ' || numZeros);
  DBMS_OUTPUT.PUT_LINE('Highest number: ' || highest);
  DBMS_OUTPUT.PUT_LINE('Lowest number: ' || lowest);
END;
/

或者,使用SQL:

DECLARE
  items    SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST(0,1,2,3,4,5);

  total    NUMBER(3,0) := 0;
  numZeros NUMBER(3,0) := 0;
  average  NUMBER(5,2) := NULL;
  highest  NUMBER(3,0) := NULL;
  lowest   NUMBER(3,0) := NULL;
BEGIN
  SELECT COALESCE(SUM(column_value),0),
         COUNT(CASE column_value WHEN 0 THEN 1 END),
         AVG(column_value),
         MAX(column_value),
         MIN(column_value)
  INTO   total,
         numZeros,
         average,
         highest,
         lowest
  FROM   TABLE(items);

  DBMS_OUTPUT.PUT_LINE('Total: ' || total);
  DBMS_OUTPUT.PUT_LINE('Average: ' || average);
  DBMS_OUTPUT.PUT_LINE('Number of zeros: ' || numZeros);
  DBMS_OUTPUT.PUT_LINE('Highest number: ' || highest);
  DBMS_OUTPUT.PUT_LINE('Lowest number: ' || lowest);
END;
/

fiddle
如果要接受用户输入,则可以将初始行替换为:

SET SERVEROUTPUT ON;

ACCEPT number_list CHAR PROMPT 'Enter a comma-delimited list of numbers:'

DECLARE
  items    SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST(&&number_list);
gajydyqb

gajydyqb2#

更改此行:

n := &amp;n;

删除n;。它应该是:

n := &amp;

我不知道你是不是弄错了这句台词:

high := n;

它应该是:

highest := n;

这一行也一样:

low := n;

其应为:

lowest := n;

之后,当我运行代码时,我得到了这个编译错误:

ORA-06502: PL/SQL: numeric or value error: number precision too large

这是因为PL/SQL没有在执行PL/SQL代码期间从用户获取输入的功能。实际上,&amp是SQL*Plus的一个功能,而不是PL/SQL的功能。该循环只是不断重复第一个输入的值(对于&amp),直到total大于999。请参阅Taking user input 'n' times PL/SQLPL/SQL: how do I prompt user input in a procedure?

相关问题