【问题标题】:How can this piece of PLSQL be made to compile?这段PLSQL如何编译?
【发布时间】:2012-11-22 04:22:34
【问题描述】:

我需要以字符串格式返回经理 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 和 or ||

谁能帮我解决这个问题?

【问题讨论】:

    标签: oracle function plsql


    【解决方案1】:

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

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

    它不会阻止函数编译,但变量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 来完成繁重的工作。

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

    【讨论】:

      【解决方案2】:

      有几点需要注意。

      • 声明为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;
      /
      

      【讨论】:

        【解决方案3】:

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

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

        您还需要在return v_name 的末尾添加分号;,例如 return v_name;

        【讨论】:

          猜你喜欢
          • 2013-12-08
          • 2017-03-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-10-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多