在 Oracle PLSQL 中遇到此 select 问题
Having problems with this select in Oracle PLSQL
我有这个代码:
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;
我一直在尝试将此 select 转换为 select 以便它可以在程序内部运行,但我尝试的任何操作都不起作用。
错误: PLS-00428: an INTO clause is expected in this SELECT statement
我知道在程序中只做一个 select 很奇怪,但我想知道它是否可能
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
回答你的问题(是否可以这样做):正如贾斯汀评论的那样,它是(有点),但你必须遵守一些规则。
例如(基于 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>
或者,您可以切换到 returns 的功能,例如参考光标:
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>
因此,是的 - 这是可能的,但这取决于您实际想做什么。
我有这个代码:
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;
我一直在尝试将此 select 转换为 select 以便它可以在程序内部运行,但我尝试的任何操作都不起作用。
错误: PLS-00428: an INTO clause is expected in this SELECT statement
我知道在程序中只做一个 select 很奇怪,但我想知道它是否可能
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
回答你的问题(是否可以这样做):正如贾斯汀评论的那样,它是(有点),但你必须遵守一些规则。
例如(基于 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>
或者,您可以切换到 returns 的功能,例如参考光标:
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>
因此,是的 - 这是可能的,但这取决于您实际想做什么。