创建存储过程时出现问题

时间:2017-12-08 15:42:40

标签: sql oracle stored-procedures cursor declare

我正在尝试按如下方式创建存储过程:

CREATE OR REPLACE PROCEDURE storedprocedure(emp number) AS
BEGIN  
  DECLARE
    -- create the cursor based on a query
    cursor emp_cursor is
      select e.employeeid, firstname, lastname, e.departmentid, e.title,
        salary, d.departmentname, billrate
      from employees e
      full join departments d on e.departmentID = d.departmentID
      full join employeeproject p on e.employeeID = p.employeeID where e.employeeID = emp;

    BEGIN
      open emp_cursor;
      -- first display information about the employee
      dbms_output.put_line('- -');
      dbms_output.put_line('- -');
      dbms_output.put_line('Employee#' || e.employeeid
        || '  Name:' || TRIM(e.firstname) || ' ' || TRIM(e.lastname)
        || ' Dept: ');
      dbms_output.put_line('_________________________________________________________');
      dbms_output.put_line('- -');
      dbms_output.put_line('- -    Title: ' || e.title
        || ' Salary: ' || to_char(e.salary,'$999,999,999.99'));
      dbms_output.put_line('- -    Billing Rate: ' || to_char(billrate,'$999,999.99'));
     -- next call the stored procedure to show department information
  END;
END;
/

但它会编译错误。当我show errors它告诉我e.employeeID时,e.titlebillrate必须全部声明,但它们是原始查询。我在这做错了什么?我误解了宣布它们的意义吗?

这些是查询表中存在的所有列,并在SQL获取结果时运行查询。

1 个答案:

答案 0 :(得分:1)

您正在打开光标,但是您没有将其提取到任何内容中 - 无论是一系列标量变量还是记录类型 - 通常都是在循环中完成的。然后,当您在循环中时,您将引用变量/记录,而不是游标查询中使用的表 - 这超出了游标声明之外的范围。

有一个稍微简单的隐式游标循环,在这种情况下你可能会觉得更容易:

CREATE OR REPLACE PROCEDURE storedprocedure(emp number) AS
BEGIN
  FOR rec IN (
    select e.employeeid, firstname, lastname, e.departmentid, e.title,
      salary, d.departmentname, billrate
    from employees e
    full join departments d on e.departmentID = d.departmentID
    full join employeeproject p on e.employeeID = p.employeeID where e.employeeID = emp
  )
  LOOP
    -- first display information about the employee
    dbms_output.put_line('- -');
    dbms_output.put_line('- -');
    dbms_output.put_line('Employee#' || rec.employeeid
      || '  Name:' || TRIM(rec.firstname) || ' ' || TRIM(rec.lastname)
      || ' Dept: ');
    dbms_output.put_line('_________________________________________________________');
    dbms_output.put_line('- -');
    dbms_output.put_line('- -    Title: ' || rec.title
      || ' Salary: ' || to_char(rec.salary,'$999,999,999.99'));
    dbms_output.put_line('- -    Billing Rate: ' || to_char(rec.billrate,'$999,999.99'));
    -- next call the stored procedure to show department information
  END LOOP;
END;
/

请注意,循环中列的所有引用都是rec.<field>形式 - 它们是循环中记录的,而不是直接来自基础表。

你也有一个嵌套的块,它没有造成任何伤害,但是没有用,所以我把它拿出来了。

如果您特别想使用显式的open-fetch-close游标处理,它将看起来像这样:

CREATE OR REPLACE PROCEDURE storedprocedure(emp number) AS
  -- create the cursor based on a query
  cursor emp_cursor is
    select e.employeeid, firstname, lastname, e.departmentid, e.title,
      salary, d.departmentname, billrate
    from employees e
    full join departments d on e.departmentID = d.departmentID
    full join employeeproject p on e.employeeID = p.employeeID where e.employeeID = emp;

   -- record variable based on cursor definition
   rec emp_cursor%ROWTYPE;

BEGIN
  OPEN emp_cursor;
  LOOP
    -- fetch the next row result from the cursor into the record vairable
    FETCH emp_cursor INTO rec;
    -- break out of the loop if there are no more results to fetch
    EXIT WHEN emp_cursor%NOTFOUND;

    -- first display information about the employee
    dbms_output.put_line('- -');
    dbms_output.put_line('- -');
    dbms_output.put_line('Employee#' || rec.employeeid
      || '  Name:' || TRIM(rec.firstname) || ' ' || TRIM(rec.lastname)
      || ' Dept: ');
    dbms_output.put_line('_________________________________________________________');
    dbms_output.put_line('- -');
    dbms_output.put_line('- -    Title: ' || rec.title
      || ' Salary: ' || to_char(rec.salary,'$999,999,999.99'));
    dbms_output.put_line('- -    Billing Rate: ' || to_char(rec.billrate,'$999,999.99'));
    -- next call the stored procedure to show department information
  END LOOP;
  CLOSE emp_cursor;
END;
/
相关问题