使用游标的存储过程
Stored procedure that uses cursor
我制作了一个使用游标生成报告的程序。它旨在 return 具有 p_qoh > avg(p_qoh)
的产品。
当我 运行 光标在过程之外时,APEX 告诉我
PLS-00204: function or pseudo-column 'AVG' may be used inside a SQL
statement only
这怎么不在 SQL 语句中?我是 SQL 的新手,只是作为 comp sci 专业的必修课 class。
这是整个街区。如果你 运行 只是光标,你就会明白我的意思。
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;
您可以将新字段添加到 type_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
为了 select 高于平均水平的薪水,您需要使用子查询。我们将此查询称为 "A" 查询(以供将来参考):
SQL> select ename, sal
2 from emp
3 where sal > (select avg(sal) from emp);
ENAME SAL
---------- ----------
JONES 2975
BLAKE 2850
CLARK 2450
KING 5000
FORD 3000
SQL>
此外,无需声明那么多 - 简单的游标 FOR 循环更易于维护:
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>
看到了吗?无需声明游标(好的,您确实在循环中使用 SELECT),键入并记录该类型,打开游标,担心何时退出循环,关闭游标。
但是,您的代码在 Apex 环境中没有多大意义。那里没有 DBMS_OUTPUT,并且使用过程创建报告(经典报告或交互式报告)是相当不寻常的;我从来没有这样做过。我使用了一个函数(这是一个 PL/SQL 代码),该函数 returns 一个 SQL 查询并基于该函数生成报告。
你的问题很简单,所以 - 使用向导,创建一个报告 - 作为它的来源 - 使用 "A" 查询(我之前提到过)。这就是你应该做的。
我制作了一个使用游标生成报告的程序。它旨在 return 具有 p_qoh > avg(p_qoh)
的产品。
当我 运行 光标在过程之外时,APEX 告诉我
PLS-00204: function or pseudo-column 'AVG' may be used inside a SQL statement only
这怎么不在 SQL 语句中?我是 SQL 的新手,只是作为 comp sci 专业的必修课 class。
这是整个街区。如果你 运行 只是光标,你就会明白我的意思。
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;
您可以将新字段添加到 type_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
为了 select 高于平均水平的薪水,您需要使用子查询。我们将此查询称为 "A" 查询(以供将来参考):
SQL> select ename, sal
2 from emp
3 where sal > (select avg(sal) from emp);
ENAME SAL
---------- ----------
JONES 2975
BLAKE 2850
CLARK 2450
KING 5000
FORD 3000
SQL>
此外,无需声明那么多 - 简单的游标 FOR 循环更易于维护:
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>
看到了吗?无需声明游标(好的,您确实在循环中使用 SELECT),键入并记录该类型,打开游标,担心何时退出循环,关闭游标。
但是,您的代码在 Apex 环境中没有多大意义。那里没有 DBMS_OUTPUT,并且使用过程创建报告(经典报告或交互式报告)是相当不寻常的;我从来没有这样做过。我使用了一个函数(这是一个 PL/SQL 代码),该函数 returns 一个 SQL 查询并基于该函数生成报告。
你的问题很简单,所以 - 使用向导,创建一个报告 - 作为它的来源 - 使用 "A" 查询(我之前提到过)。这就是你应该做的。