SQL - 使用Cursor&实施声明

时间:2012-11-25 19:56:37

标签: sql oracle

CREATE OR REPLACE procedure verify_employee IS
Emp_name trkemployee.name#%TYPE,
Emp_ID trkemployee.E#%TYPE,

CURSOR c1;
IS
select e.e#, e.name from trkemployee e where e# IN (select e# from trkdriver intersect select e# from trkmechanic);
IN 
(select e# from trkdriver intersect select e# from trkmechanic);
BEGIN
OPEN c1();

LOOP

END LOOP;
close c1;
END;
/

以上是我的PL / SQL代码..我想要实现的是列出所有以司机身份工作的员工。机械师同时..

我在终端单独执行sql语句,输出如下:

SQL> select e.e#, e.name from trkemployee e where e# IN (select e# from trkdriver intersect select e# from trkmechanic);

        E# NAME
---------- --------------------------------------------------
        14 Andrew R. Smith

但我想在PL / SQL中执行此操作并执行DMBS_OUTPUT.PUT(结果);

我知道检查多条记录,我需要使用光标。假设将来会有超过1行返回,我应该如何更改我的pl / sql,当我加载程序时,终端说有编译错误。

以下是我的3张桌子..

SQL> desc trkdriver;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------

 E#                                        NOT NULL NUMBER(12)
 L#                                        NOT NULL NUMBER(8)
 STATUS                                    NOT NULL VARCHAR2(10)

SQL> desc trkmechanic;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------

 E#                                        NOT NULL NUMBER(12)
 L#                                        NOT NULL NUMBER(8)
 STATUS                                    NOT NULL VARCHAR2(10)
 EXPERIENCE                                NOT NULL VARCHAR2(10)


SQL> desc trkemployee;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------

 E#                                        NOT NULL NUMBER(12)
 NAME                                      NOT NULL VARCHAR2(50)
 DOB                                                DATE
 ADDRESS                                   NOT NULL VARCHAR2(300)
 HIREDATE                                  NOT NULL DATE

1 个答案:

答案 0 :(得分:2)

您的代码中有两次IN (select ....部分。我认为这就是编译错误的意义所在。

我还认为2 in会更快,因为Oracle可能会更好地使用这些索引:

select 
  e.e#, 
  e.name 
from 
  trkemployee e 
where 
  e# IN (select e# from trkdriver)
  and e# in (select e# from trkmechanic);

提示:如果使用这样的游标,则需要添加大量异常处理,以防止游标在出现错误时保持打开状态。 for循环使游标循环更容易,更安全:

for r in C loop
  DBMS_OUTPUT.PUT_LINE(r.e#);
end loop;

另外,我可以想象e#是一个可能导致PL / SQL出现问题的字段名称。我不确定,但如果你遇到编译错误,可能就是这种情况。我宁愿选择像'EmployeeNr`这样更常见的名字。

[编辑]

您的代码有几个错误。首先,;之后的cursor C1不应该存在。此外,循环中没有代码,这在PL / SQL中是不允许的。如果您需要对其进行测试,但尚未编写代码,则可以键入null;作为“无效的代码”。像:

loop
  null;
end loop;

您的整个代码可能如下所示。这个实际上是编译的,应该让你用你可能需要的其他东西完成它。

CREATE OR REPLACE PROCEDURE verify_employee IS

  CURSOR C1 IS
    SELECT
      E.E#,
      E.name
    FROM
      trkemployee E
    WHERE
      E# IN (SELECT E# FROM trkdriver)
      AND E# IN (SELECT E# FROM trkmechanic);

BEGIN
  -- R becomes an alias for each row. You can access the fields
  -- of the rows inside the loop
  FOR R IN C1 LOOP
    -- Output each Emplyee number.
    DBMS_OUTPUT.PUT_LINE(R.E# || ', ' || r.name);
  END LOOP;
END;