如何编译这段PLSQL?

时间:2012-11-22 04:22:34

标签: oracle function plsql

我需要为经理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:   遇到符号“;”当期待以下之一:)   ,*& - + / at mod remaining rem和or ||

有人可以帮我吗?

3 个答案:

答案 0 :(得分:5)

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

  1. 您已声明变量v_names并将其引用为v_name
  2. PL / SQL中的赋值运算符为:=,您使用的是等于运算符=
  3. 你的回复陈述中遗漏了一个分号;它应该是return v_name;
  4. 它不会停止编译函数,但变量v_names被声明为varchar2(10)。当具有多个下属的经理所有姓氏都适合这种情况时,这种情况极不可能发生。您应该使用最大大小声明此变量;以防万一。

    我想补充一点,你这样做的效率非常低。如果你要在SQL中进行字符串聚合而不是PL / SQL循环,那就更好了。从11g第2版开始,您拥有listagg()功能;如果您之前使用的版本有足够的other string aggregation techniques来获得相同的结果。

    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做了繁重的工作。
    5. 你想要返回一个以逗号分隔的列表,这很奇怪,因为在Oracle之后你几乎无法用它做什么。返回类似数组的内容或包含所有姓氏的开放游标可能更为正常。在这个答案中,我假设你有充分的理由去做你自己。

答案 1 :(得分:3)

有几点需要注意。

  • 声明为v_names但用作v_name

  • Assignemnt应该像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;
/

答案 2 :(得分:1)

我猜您应该使用:=代替=

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

还需要在;末尾添加分号return v_name return v_name;