【问题标题】:Issue when creating a stored procedure创建存储过程时的问题
【发布时间】:2018-05-22 21:23:44
【问题描述】:

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

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.employeeIDe.titlebillrate 都必须声明,但它们是原始查询。我在这里做错了什么?我是否误解了声明它们的含义?

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

【问题讨论】:

  • 请标记您正在使用的特定 SQL 产品 - SQL Server、Oracle、MySQL、PostgreSQL 等。
  • 会的,我用的是oracle。我现在就加标签
  • 使用格式有点难以阅读,但您需要某种循环构造和 fetch 以循环游标。请记住,在 SQL 数据库中,游标通常应该是最后的手段。通常最好使用基于集合的方法。

标签: sql oracle stored-procedures cursor declare


【解决方案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;
/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-18
    • 2016-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-16
    • 2022-01-13
    相关资源
    最近更新 更多