1

对于经理 ID 取决于传递的参数的所有员工,我需要以字符串格式返回员工的姓名。当我编译该函数时,我得到一个错误。这是功能代码:

create or replace function Employee(v_manid IN employees.manager_id%type) 
return varchar2
AS
cursor cur_emp is select last_name from employees where manager_id = v_manid;
v_names varchar2(10);
begin
for emp_rec in cur_emp
loop
v_name = v_name || emp_rec.last_name ||', ';
end loop;
return v_name
end;
/

错误是:

错误(8,8):PLS-00103:在预期以下之一时遇到符号“=”::=。( @ % ; 错误 (8,44): PLS-00103: 遇到符号 ";" 当期望以下之一时:) , * & - + / 在 mod 余数 rem 和或 ||

谁能帮我解决这个问题?

4

3 回答 3

5

如其他答案所述,您的函数无法编译的原因是三重的。

  1. 您已声明变量v_names并将其引用为v_name.
  2. PL/SQL 中的赋值运算符是:=,您使用的是相等运算符=
  3. 您的 return 语句中缺少分号;它应该是return v_name;

它不会停止函数编译,但变量v_names被声明为varchar2(10). 当一个拥有多个下属的经理的所有姓氏都适合这种情况时,这是极不可能的。您可能应该使用最大大小声明此变量;以防万一。

我想补充一点,您这样做的效率非常低。如果您要在 SQL 中而不是 PL/SQL 循环中进行字符串聚合,那会更好。从 11g 第 2 版开始,您拥有该listagg()功能;如果您使用的是之前的版本,那么还有很多其他字符串聚合技术可以实现相同的结果。

create or replace function employee ( p_manid in employees.manager_id%type
      ) return varchar2 is

   v_names varchar2(32767); -- Maximum size, just in case

begin

   select listagg(lastname, ', ') within group ( order by lastname )
     into v_names
     from employees 
    where manager_id = p_manid;

   return v_names;

exception when no_data_found then
   return null;

end;
/

请注意我所做的其他一些更改:

  1. 在函数参数上附加一个与变量不同的字母,以明确哪个是哪个。
  2. 添加一些异常处理以处理该特定经理没有数据。
  3. ,如果你没有数据我会返回 NULL,你会返回。如果您想返回逗号,只需将其放在异常中即可。
  4. 我没有费心创建游标并循环遍历它等,而是让 Oracle 完成繁重的工作。

很奇怪,您想要返回一个逗号分隔的列表,因为之后您在 Oracle 中几乎无法使用它。返回诸如包含所有姓氏的数组或打开游标之类的东西可能更正常。在这个答案中,我假设您有充分的理由去做自己的事情。

于 2012-11-22T08:21:21.333 回答
3

有几点需要注意。

  • 声明为v_names但用作v_name

  • 分配应该像v_name := v_name || emp_rec.last_name || ', ';

  • v_name声明的大小为 10,它太小了,执行时会报错,所以你可以声明为

    v_name employees.last_name%TYPE;

您可以将您的功能创建为

CREATE OR REPLACE FUNCTION employee (v_manid IN employees.manager_id%TYPE)
        RETURN VARCHAR2
       AS
        v_name  employees.last_name%TYPE;
        CURSOR cur_emp
        IS
            SELECT  last_name
              FROM  employees
             WHERE  manager_id = v_manid;
    BEGIN
        FOR emp_rec IN cur_emp
        LOOP
            v_name := v_name || emp_rec.last_name || ', ';
        END LOOP;

        RETURN v_name;
    END;
/
于 2012-11-22T04:54:28.003 回答
1

我想你应该使用:=而不是= 喜欢

v_name := v_name || emp_rec.last_name ||', ';

还有一件事,您还需要在like ;的末尾添加分号return v_namereturn v_name;

于 2012-11-22T04:32:39.117 回答