2016-12-07 24 views
2

我正在练习PLSQL,我正在编写一个包含两个函数的包来更新佣金,另一个更新薪水,但现在我想在同一个包中创建一个过程,以更新所有使用函数的员工的佣金和工资在包裹上。可能吗?如何在过程中调用函数来更新PLSQL上的表的所有记录?

CREATE OR REPLACE PACKAGE BODY emp_upd_pkg IS 

    -- Function to update commission_pct -- 
    FUNCTION comm_upd(
    p_empid employees.commission_pct%TYPE) 
    RETURN NUMBER 
    IS 
    v_new_comm employees.commission_pct%TYPE; 
    BEGIN 
    UPDATE employees 
    SET commission_pct = commission_pct * 1.1 
    WHERE employee_id = p_empid; 

    SELECT commission_pct 
    INTO v_new_comm 
    FROM employees 
    WHERE employee_id = p_empid; 
    RETURN v_new_comm; 
    EXCEPTION 
    WHEN 
     NO_DATA_FOUND THEN 
     RAISE_APPLICATION_ERROR(-20992, 'NO EXISTE EMPLEADO'); 
    END comm_upd; 

    -- Function to update salary -- 
    FUNCTION sal_upd(
    p_empid employees.salary%TYPE) 
    RETURN employees.salary%TYPE 
    IS 
    v_newsal employees.salary%TYPE; 
    BEGIN 
    UPDATE employees 
    SET salary = salary + 350 
    WHERE employee_id = p_empid; 

    -- Consulta select para la salida del a funcion -- 
    SELECT salary 
    INTO v_newsal 
    FROM employees 
    WHERE employee_id = p_empid; 
    RETURN v_newsal; 
    END sal_upd; 

    -- Procedure to update all records of employees table -- 
    PROCEDURE comm_sal_upd(
    p_new_comm employees.commission_pct%TYPE, 
    p_new_sal employees.salary%TYPE); 

END emp_upd_pkg; 

我试过创建一个游标和获取功能,但我没有成功。

PROCEDURE comm_sal_upd(
    p_new_comm employees.commission_pct%TYPE, 
    p_new_sal employees.salary%TYPE) 
    IS 
CURSOR emp_cur IS 
    SELECT commission_pct, salary 
    FROM employees; 
BEGIN 
    OPEN emp_cur; 
    FETCH emp_cur 
    INTO emp_upd_pkg.comm_upd(p_comm), emp_upd_pkg.sal_upd(p_sal); 
    CLOSE emp_cur; 
END comm_sal_upd; 
+1

你的功能会更有意义的过程。你也传入employee_ids,所以他们应该是'employees.employee_id%TYPE'。 –

+0

你想'comm_dal_upd'做什么?是否应该对所有员工应用指定的佣金和薪资调整?如果是这样,您的佣金和工资程序/函数应接受'p_new_comm'和'p_new_sal'作为参数,并使用它们代替硬编码值。 –

+0

感谢您的回复。其实我认为你是对的,所以是否可以编写一个过程,然后使用RETURNING属性作为comm_sal_upd过程的参数? - com,_sal_upd是一个过程,用于使用comm_upd和sal_upd函数更新所有雇员的工资和调用。 – Rattlesnake

回答

1

首先,很少有技巧来提高你的功能。

当你可以制作一个时,你不需要做两个查询。取而代之的

v_new_comm employees.commission_pct%TYPE; 
BEGIN 
    UPDATE employees 
    SET commission_pct = commission_pct * 1.1 
    WHERE employee_id = p_empid; 

    SELECT commission_pct 
    INTO v_new_comm 
    FROM employees 
    WHERE employee_id = p_empid; 
    RETURN v_new_comm; 

使用returning条款:

v_new_comm employees.commission_pct%TYPE; 
BEGIN 
    UPDATE employees 
    SET commission_pct = commission_pct * 1.1 
    WHERE employee_id = p_empid 
    returning commission_pct 
    into v_new_comm; 

    RETURN v_new_comm; 

而且,这种异常块看起来并不像非常有帮助:

EXCEPTION 
    WHEN 
    NO_DATA_FOUND THEN 
     RAISE_APPLICATION_ERROR(-20992, 'NO EXISTE EMPLEADO'); 

你只需要改变错误消息的语言。

至于更新所有记录的过程中,有几个问题:

  • 你应该避免更新多条记录一个接一个,它显著降低性能。如果可能,一起更新它们:

    UPDATE employees 
    SET commission_pct = commission_pct * 1.1, 
         salary = salary + 350; 
    
  • 游标不能这样工作。你推荐使用它们来选择数据。

  • 要处理游标中的所有行,使用循环:

    PROCEDURE comm_sal_upd(
        p_new_comm employees.commission_pct%TYPE, 
        p_new_sal employees.salary%TYPE) 
        IS 
    CURSOR emp_cur IS 
        SELECT commission_pct, salary 
        FROM employees; 
        v_comission number; 
        v_salary number; 
    BEGIN 
        OPEN emp_cur; 
        loop 
        FETCH emp_cur INTO v_comission, v_salary; 
        EXIT WHEN emp_cur%NOTFOUND; 
        <do something> 
        end loop; 
        CLOSE emp_cur; 
    END comm_sal_upd; 
    

有了一个FETCH你只能处理一个记录。

+0

感谢您的回复。你是对的,现在我有一个代码这个过程的想法。但重点是我需要使用该功能的程序。我现在会尝试。 – Rattlesnake

1

您正在使用函数,因此它的returing一个值。你必须捕捉你的程序中的值如下:

PROCEDURE comm_sal_upd(
    p_new_comm employees.commission_pct%TYPE, 
    p_new_sal employees.salary%TYPE) 
    IS 
CURSOR emp_cur IS 
    SELECT commission_pct, salary 
    FROM employees; 

    var number; 
    var2 employees.salary%TYPE; 

BEGIN 

    for rec in emp_cur 
    loop 

    var:= emp_upd_pkg.comm_upd(p_comm); 
    var2:=emp_upd_pkg.sal_upd(p_sal); 

    dbms_output.put_line('updated commission--'|| var || ' Updated Sal -- '|| var2); 

    end loop; 

commit; 
END comm_sal_upd; 
+0

是的,你是对的,但我没有任何想法如何使它!我会尝试使用您的代码,稍后将粘贴我的新代码。谢谢 – Rattlesnake

+0

我已经在我的解决方案中给出了这个想法。逐行阅读。 – XING

0

我认为以下是你正在尝试做的事情。 (未经测试,可能有错误。)注意,这是在PL/SQL中执行任何操作最低效的方式,所以这只是为了演示如何构建可相互调用的过程。

(顺便说一句,我不知道是否有一些教科书在那里,告诉人们在大写字母的代码,但我们实在没有必要。)

create or replace package body emp_upd_pkg 
as 
    -- Update commission_pct for one employee: 
    procedure comm_upd 
     (p_empid  employees.employee_id%type 
     , p_new_comm employees.commission_pct%type) 
    is 
    begin 
     update employees set commission_pct = commission_pct * p_new_comm 
     where employee_id = p_empid; 

     if sql%rowcount = 0 then 
      raise_application_error(-20992, 'Commission update failed: employee id ' || p_empid || ' not found.', false); 
     end if; 
    end comm_upd; 


    -- Update salary for one employee: 
    procedure sal_upd 
     (p_empid employees.employee_id%type 
     , p_new_sal employees.salary%type) 
    is 
    begin 
     update employees set salary = salary + p_new_sal 
     where employee_id = p_empid; 

     if sql%rowcount = 0 then 
      raise_application_error(-20993, 'Salary update failed: employee id ' || p_empid || ' not found.', false); 
     end if; 
    end sal_upd; 


    -- Update all employees: 
    procedure comm_sal_upd 
     (p_new_comm employees.commission_pct%type 
     , p_new_sal employees.salary%type) 
    is 
    begin 
     for r in (
      select employee_id from employees 
     ) 
     loop 
      comm_upd(r.employee_id, p_new_comm); 
      sal_upd(r.employee_id, p_new_sal); 
     end loop; 
    end comm_sal_upd; 

end emp_upd_pkg; 
相关问题