在 Oracle 中,当 PL/SQL 代码使用 SELECT 语句时,您必须选择 进入 某些东西 - 局部变量、集合等 - 或使用游标循环并处理游标变量。
您正在选择volume 值第二大的行。您编写的代码工作,但它从同一个表中提取了 3 次,这不是最佳的。例如(基于 Scott 的示例模式),获取第二大薪水:
SQL> select ename, sal from emp order by sal desc;
ENAME SAL
---------- ----------
KING 5000 --> largest
FORD 3000 --> Ford and Scott both share
SCOTT 3000 --> the 2nd largest salary
JONES 2975
BLAKE 2850
CLARK 2450
<snip>
您的查询返回正确的结果:
SQL> select *
2 from emp
3 where sal = (select max(sal) from emp
4 where sal not in (select max(sal) from emp)
5 );
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7788 SCOTT ANALYST 7566 09.12.82 3000 20
7902 FORD ANALYST 7566 03.12.81 3000 20
考虑换一种方式:
SQL> select *
2 from (select e.*,
3 rank() over (order by sal desc) rnk
4 from emp e
5 )
6 where rnk = 2;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO RNK
---------- ---------- --------- ---------- -------- ---------- ---------- ---------- ----------
7788 SCOTT ANALYST 7566 09.12.82 3000 20 2
7902 FORD ANALYST 7566 03.12.81 3000 20 2
SQL>
现在,回到您的程序。一个不需要太多努力的简单选项是使用游标FOR 循环。程序的IN 参数表示你想要的最高薪水:
SQL> create or replace procedure nearthetop (par_n in number) as
2 begin
3 for cur_r in (select *
4 from (select e.*,
5 rank() over (order by sal desc) rnk
6 from emp e
7 )
8 where rnk = par_n
9 )
10 loop
11 dbms_output.put_line(cur_r.ename ||': '|| cur_r.sal);
12 end loop;
13 end;
14 /
Procedure created.
测试:
SQL> set serveroutput on
SQL> begin
2 nearthetop(2); --> give me the 2nd largest salary
3 end;
4 /
SCOTT: 3000
FORD: 3000
PL/SQL procedure successfully completed.
SQL> begin
2 nearthetop(5); --> give me the 5th largest salary
3 end;
4 /
BLAKE: 2850
PL/SQL procedure successfully completed.
SQL>
我只是在屏幕上显示这些值;你从来没有说过你想对他们做什么。
如果您想将结果返回给调用者,更好的选择是使用函数而不是过程。在这种情况下,它会返回一个引用游标。
SQL> create or replace function f_nearthetop (par_n in number)
2 return sys_refcursor
3 as
4 rc sys_refcursor;
5 begin
6 open rc for select *
7 from (select e.*,
8 rank() over (order by sal desc) rnk
9 from emp e
10 )
11 where rnk = par_n;
12 return rc;
13 end;
14 /
Function created.
测试:
SQL> var l_rc refcursor
SQL>
SQL> exec :l_rc := f_nearthetop(2);
PL/SQL procedure successfully completed.
SQL> print :l_rc
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO RNK
---------- ---------- --------- ---------- -------- ---------- ---------- ---------- ----------
7788 SCOTT ANALYST 7566 09.12.82 3000 20 2
7902 FORD ANALYST 7566 03.12.81 3000 20 2
SQL>
所以,是的 - 有多种选择。您实际使用哪一个取决于您想做什么。
(截至 Visual Studio:我无能为力,我不使用它。)