2012-11-22 79 views
1

我需要以管理員標識依賴於傳遞參數的所有員工的字符串格式返回員工姓名。當我編譯函數時,我得到一個錯誤。下面是函數的代碼:這塊PLSQL如何編譯?

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 remainder rem and or ||

任何人都可以幫助我嗎?

回答

5

正如在其他的答案爲什麼你的功能將不能編譯的原因說是一舉三得。

  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中使用逗號分隔列表。返回類似數組或包含所有姓氏的開放遊標可能更爲正常。我認爲,在這個答案中,你有充分的理由去做你自己。

+0

+一個很好的解釋。 – user75ponic

1

我猜你應該使用:=代替=

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

一件事,你還需要在return v_name末加上分號;return v_name;

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; 
/