在 Oracle PLSQL 中此选择存在问题
Posted
技术标签:
【中文标题】在 Oracle PLSQL 中此选择存在问题【英文标题】:Having problems with this select in Oracle PLSQL 【发布时间】:2021-12-29 01:43:56 【问题描述】:我有这个代码:
create view nombres_lab as
select L.NOMBRE_LAB, R.NOM_REG, count(*) as vacunas_suministradas
from LABORATORios L
inner join CREA_VACUNAS CV on l.cod_lab = cv.cod_lab
inner join vacunas V on cv.cod_vac = v.cod_vac
inner join vtorio VT on v.cod_vac = vt.cod_vac
inner join datos_vac_sum DVS on vt.cod_vtorio = dvs.cod_vtorio
inner join frasco_vac FV on dvs.s_unica = fv.s_unica
inner join direccion D on vt.cod_dir = d.cod_dir
inner join region R on d.cod_reg = r.cod_reg
where v.cod_vac = 100202 or v.cod_vac = 100303
group by l.nombre_lab, r.nom_reg;
create or replace procedure ranking is
begin
select nombre_lab, nom_reg, count(*) as vacunas_suministradas, rank() over(order by count(*) desc) as ranking from nombres_lab group by nom_reg, nombre_lab;
end;
我一直在尝试将此选择转换为选择转换,以便它可以在过程中工作,但我尝试的任何方法都不起作用。
错误: PLS-00428: an INTO clause is expected in this SELECT statement
我知道只在过程中进行选择很奇怪,仅此而已,但我想知道它是否可能
【问题讨论】:
您希望该过程做什么?你不能有一个只是一个查询的过程。您可以将过程定义为具有sys_refcursor
类型的out
参数,以便它将引用游标返回给调用者。但在这种情况下,将其定义为函数而不是过程可能更有意义。您在视图定义和查询中复制逻辑似乎很奇怪——也许您想在第一个视图之上创建第二个视图,而不是创建一个过程。
您遇到的错误是什么。 rank 函数中的 count(*) 似乎是个问题。您可以在 CTE 中单独执行此操作,然后再执行 rank() ....
【参考方案1】:
回答你的问题(是否可以做这样的事情):正如贾斯汀所说,它是(有点),但你必须遵守一些规则。
例如(基于 Scott 的架构,因为我没有你的表):
SQL> CREATE OR REPLACE VIEW nombres_lab
2 AS
3 SELECT deptno nombre_lab, job nom_reg FROM emp;
View created.
这是一个修复您遇到的错误的过程(“此 SELECT 语句中需要一个 INTO 子句”):声明一些局部变量并select into
它们。
SQL> CREATE OR REPLACE PROCEDURE ranking
2 IS
3 l_nombre_lab nombres_lab.nombre_lab%TYPE;
4 l_nom_reg nombres_lab.nom_reg%TYPE;
5 l_vacunas_suministradas NUMBER;
6 l_ranking NUMBER;
7 BEGIN
8 SELECT nombre_lab,
9 nom_reg,
10 COUNT (*),
11 RANK () OVER (ORDER BY COUNT (*) DESC)
12 INTO l_nombre_lab,
13 l_nom_reg,
14 l_vacunas_suministradas,
15 l_ranking
16 FROM nombres_lab
17 GROUP BY nom_reg, nombre_lab;
18 END;
19 /
Procedure created.
它会起作用吗?不幸的是,没有。但是,如果查询只返回一行,它会:
SQL> EXEC ranking;
BEGIN ranking; END;
*
ERROR at line 1:
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at "SCOTT.RANKING", line 8
ORA-06512: at line 1
那么,该怎么办?您可以使用循环(然后您不需要任何变量也不需要into
子句)并处理获取的值。我没有任何聪明的想法,所以我只是显示光标返回的内容:
SQL> CREATE OR REPLACE PROCEDURE ranking
2 IS
3 BEGIN
4 FOR cur_r IN ( SELECT nombre_lab,
5 nom_reg,
6 COUNT (*) vacunas_suministradas,
7 RANK () OVER (ORDER BY COUNT (*) DESC) ranking
8 FROM nombres_lab
9 GROUP BY nom_reg, nombre_lab)
10 LOOP
11 DBMS_OUTPUT.put_line (
12 cur_r.nombre_lab
13 || ' - '
14 || cur_r.nom_reg
15 || ' - '
16 || cur_r.vacunas_suministradas
17 || ' - '
18 || cur_r.ranking);
19 END LOOP;
20 END;
21 /
Procedure created.
SQL> SET SERVEROUTPUT ON
SQL> EXEC ranking;
30 - SALESMAN - 4 - 1
20 - ANALYST - 2 - 2
20 - CLERK - 2 - 2
20 - MANAGER - 1 - 4
30 - CLERK - 1 - 4
30 - MANAGER - 1 - 4
10 - MANAGER - 1 - 4
10 - CLERK - 1 - 4
10 - PRESIDENT - 1 - 4
PL/SQL procedure successfully completed.
SQL>
或者,您可以切换到返回例如的函数。参考光标:
SQL> CREATE OR REPLACE FUNCTION f_ranking
2 RETURN SYS_REFCURSOR
3 IS
4 rc SYS_REFCURSOR;
5 BEGIN
6 OPEN rc FOR SELECT nombre_lab,
7 nom_reg,
8 COUNT (*),
9 RANK () OVER (ORDER BY COUNT (*) DESC)
10 FROM nombres_lab
11 GROUP BY nom_reg, nombre_lab;
12
13 RETURN rc;
14 END;
15 /
Function created.
SQL> var l_rc refcursor
SQL> exec :l_rc := f_ranking
PL/SQL procedure successfully completed.
SQL> print l_rc
NOMBRE_LAB NOM_REG COUNT(*) RANK()OVER(ORDERBYCOUNT(*)DESC)
---------- --------- ---------- -------------------------------
30 SALESMAN 4 1
20 ANALYST 2 2
20 CLERK 2 2
20 MANAGER 1 4
30 CLERK 1 4
30 MANAGER 1 4
10 MANAGER 1 4
10 CLERK 1 4
10 PRESIDENT 1 4
9 rows selected.
SQL>
因此,是的 - 有可能,但这取决于您实际想要做什么。
【讨论】:
【参考方案2】:rank 函数中的 count(*) 似乎是个问题。试试下面,我认为应该可以解决问题。
WITH nombre_lab_summary AS
(
SELECT
nombre_lab,
nom_reg,
COUNT(*) AS vacunas_suministradas,
FROM nombres_lab
GROUP BY
nom_reg,
nombre_lab
)
SELECT
*,
RANK() OVER (ORDER BY vacunas_suministradas DESC) AS ranking
FROM nombre_lab_summary
GROUP BY
nom_reg,
nombre_lab
【讨论】:
RANK 内的 COUNT 不是问题。这是完全有效的。你不相信我吗?运行select rank() over (order by count(*) desc) as ranking from dual;
看看。以上是关于在 Oracle PLSQL 中此选择存在问题的主要内容,如果未能解决你的问题,请参考以下文章