Stored procedures 使用游标的存储过程

Stored procedures 使用游标的存储过程,stored-procedures,plsql,cursor,oracle-apex,Stored Procedures,Plsql,Cursor,Oracle Apex,我制作了一个使用光标生成报告的过程。它设计用于返回具有p\u qoh>avg(p\u qoh)的产品 当我在过程外部运行光标时,APEX会告诉我 PLS-00204:函数或伪列“AVG”可在SQL中使用 仅声明 这怎么不在SQL语句中呢?我是新来SQL的,只是一门必修的计算机科学专业 这是整个街区。如果你只运行光标,你就会明白我的意思 CREATE OR REPLACE PROCEDURE prod_rep IS CURSOR cur_qoh IS SELECT p_qoh, p_

我制作了一个使用光标生成报告的过程。它设计用于返回具有
p\u qoh>avg(p\u qoh)
的产品

当我在过程外部运行光标时,APEX会告诉我

PLS-00204:函数或伪列“AVG”可在SQL中使用 仅声明

这怎么不在SQL语句中呢?我是新来SQL的,只是一门必修的计算机科学专业

这是整个街区。如果你只运行光标,你就会明白我的意思

CREATE OR REPLACE PROCEDURE prod_rep
IS 
  CURSOR cur_qoh IS
    SELECT p_qoh, p_descript, p_code
      FROM xx_product;

  TYPE type_prod IS RECORD(
    prod_qoh    xx_product.p_qoh%TYPE,
    prod_code   xx_product.p_code%TYPE,
    prod_descr  xx_product.p_descript%TYPE);

  rec_prod type_prod;
BEGIN
  OPEN cur_qoh;
  LOOP
    FETCH cur_qoh INTO rec_prod;
    EXIT WHEN cur_qoh%NOTFOUND;

    IF rec_prod.prod_qoh > avg(rec_prod.prod_qoh) THEN
       DBMS_OUTPUT.PUT_LINE(rec_prod.prod_code||' -> '||rec_prod.prod_desc);
    END IF;
  END LOOP;
  CLOSE cur_qoh;
END;
更新:工作块

BEGIN 
 FOR cur_r IN (SELECT p_qoh, p_descript, p_code FROM xx_product
        WHERE p_qoh > (SELECT avg(p_qoh) FROM xx_product))
LOOP
  DBMS_OUTPUT.PUT_LINE(cur_r.p_code||' -> '|| cur_r.p_descript);
 END LOOP;
END;

此时,您进入的是PL/SQL,而不是SQL。 您可以在SQL查询中使用分析函数AVG来获得平均值:

CURSOR cur_qoh IS
SELECT p_qoh, p_descript, p_code, AVG(p_goh) OVER () as p_goh_avg
  FROM xx_product;
您可以将新字段添加到类型_prod:

  TYPE type_prod IS RECORD(
    prod_qoh    xx_product.p_qoh%TYPE,
    prod_code   xx_product.p_code%TYPE,
    prod_descr  xx_product.p_descript%TYPE,
    prod_avg    xx_product.p_qoh%TYPE)
   ;
然后你可以将你的平均值应用到循环中:

IF rec_prod.prod_qoh > rec_prod.prod_avg THEN
在PL/SQL循环中使用AVG是没有意义的。PL/SQL是过程性的,此时您不会处理整个数据集:一次只管理一行。而SQL则处理数据集

使用分析函数,您可以得到每一行上的列的平均值,这样您就可以在PL/SQL循环中管理它。

是的,这是(PL/)SQL,但您不能这样使用AVG。看一看:这是一个基于Scott模式的示例

平均工资是

SQL> select avg(sal) from emp;

  AVG(SAL)
----------
2077,08333
为了选择高于平均工资的工资,您需要使用子查询。让我们将此查询称为“A”查询(供将来参考):

此外,无需声明太多内容-简单的循环游标更易于维护:

SQL> create or replace procedure prod_rep as
  2  begin
  3    for cur_r in (select ename, sal from emp
  4                  where sal > (select avg(sal) from emp))
  5    loop
  6      dbms_output.put_line(cur_r.ename ||' '|| to_char(cur_r.sal, '9990'));
  7    end loop;
  8  end;
  9  /

Procedure created.

SQL> begin prod_rep; end;
  2  /
JONES  2975
BLAKE  2850
CLARK  2450
KING  5000
FORD  3000

PL/SQL procedure successfully completed.

SQL>
看到了吗?无需声明游标(好的,您在循环中使用该选择)、该类型的类型和记录、打开游标、担心何时退出循环、关闭游标


然而,您的代码在Apex环境中并没有多大意义。这里没有DBMS_输出,使用过程创建报告(经典报告或交互式报告)是非常罕见的;我从来没有这样做过。我使用了一个函数(这是一个PL/SQL代码),它返回一个SQL查询并基于该查询生成报告


您的问题很简单,因此-使用向导,创建一个报告,并作为其来源-使用“a”查询(我前面提到过)。这就是你应该做的。

谢谢!我对它进行了更新,以包含我在您的帮助下创建的有效块,但当我尝试将其放入一个过程中时,它返回“successwithcompilationerror”CREATE,而CREATE只是创建一个过程。您必须执行它才能运行其代码并获得结果-这就是我的
beginprod\u rep;结束/块执行。确保启用输出,即运行
将serveroutput设置为on
(否则您将在屏幕上看不到任何内容)。我的错误是,我缺少AS关键字。它现在编译正确了。谢谢你的帮助!
SQL> create or replace procedure prod_rep as
  2  begin
  3    for cur_r in (select ename, sal from emp
  4                  where sal > (select avg(sal) from emp))
  5    loop
  6      dbms_output.put_line(cur_r.ename ||' '|| to_char(cur_r.sal, '9990'));
  7    end loop;
  8  end;
  9  /

Procedure created.

SQL> begin prod_rep; end;
  2  /
JONES  2975
BLAKE  2850
CLARK  2450
KING  5000
FORD  3000

PL/SQL procedure successfully completed.

SQL>