使用游标来完成一个表

时间:2013-05-10 17:18:03

标签: sql oracle plsql cursor

这是我的情景: 我有一个表Employees我只需要考虑一个属性(工资),所有其他属性都不需要进行练习。我必须创建另一个表(least_earners)并在此表中插入员工的最后一个n(从用户输入)收入者。

我已经这样做了,但我想知道是否可以,或者我是否犯了错误(我正在使用Oracle DB和PL / SQL)。可以在不创建对象之前创建表吗?它是否像使用SQL的正常创建一样工作?

DECLARE
 bottom_n_salaries 
   NUMBER := &bottom_salaries;
 CURSOR emp_cursor IS
   SELECT DISTINCT salary 
   FROM employees
   ORDER BY salary ASC;
 CREATE TYPE least_earners_obj 
   AS OBJECT (salary NUMBER(8));
 CREATE TYPE least_earners 
   AS TABLE OF least_earners_obj;
BEGIN
 OPEN emp_cursor;
   LOOP
     INSERT INTO least_earners 
     VALUE(FETCH emp_cursor);
   EXIT WHEN emp_cursor%ROWCOUNT >bottom_n_salaries
   OR emp_cursor%NOTFOUND;
   END LOOP;
 CLOSE emp_cursor;
END;

1 个答案:

答案 0 :(得分:0)

您不需要PL / SQL来执行此操作,但您可以使用它。您可以使用CREATE table AS ...

CREATE TABLE least_earners AS
  SELECT sal FROM (
    SELECT sal
    FROM employees
    ORDER BY sal)
  WHERE ROWNUM <= &bottom_salaries

如果表格已经存在,您可以使用INSERT INTO table SELECT ...

INSERT INTO least_earners (sal)
  SELECT sal FROM (
    SELECT sal
    FROM employees
    ORDER BY sal)
  WHERE ROWNUM <= &bottom_salaries

如果您的作业需要PL / SQL,则上面的代码中会出现一些错误(附录:我基于INSERT ... FETCH,但我可能错了),而且它也是如此除非你需要使用对象,否则手头的任务很复杂。


附录带光标的PL / SQL是必需的,因此相应地调整了答案......

首先是几点:

  • 我不认为INSERT INTO least_earners VALUE(FETCH emp_cursor)是有效的语法,但我不在我可以测试它的地方。以下示例不使用它。

  • 您正在插入另一个表格并随后检查%NOTFOUND 。你需要先做。

总的来说这样的事情应该做,但正如我上面提到的,我不在一个可以测试它的地方。可能需要调整:

DECLARE
 bottom_n_salaries NUMBER := &bottom_salaries;
 thisSalary NUMBER;
 CURSOR emp_cursor IS
   SELECT DISTINCT salary 
   FROM employees
   ORDER BY salary ASC;
BEGIN
 OPEN emp_cursor;
   LOOP
     FETCH emp_cursor INTO thisSalary;
     EXIT WHEN emp_cursor%ROWCOUNT > bottom_n_salaries
            OR emp_cursor%NOTFOUND;
     INSERT INTO least_earners VALUES (thisSalary);
   END LOOP;
 CLOSE emp_cursor;
END;

如果移动EXIT WHEN搞砸了你的“底薪”逻辑,你可以进行两次EXIT尝试:

     ...
     EXIT WHEN emp_cursor%NOTFOUND;
     INSERT INTO least_earners VALUES (thisSalary);
     EXIT WHEN emp_cursor%ROWCOUNT > bottom_n_salaries;
     ...