如何调用过程中的函数来更新PLSQL上表的所有记录?

时间:2016-12-07 06:05:22

标签: sql oracle plsql

我正在练习PLSQL,我编写了一个包含2个函数的软件包来更新佣金,另一个用于更新工资,但现在我想在同一个软件包中创建一个程序来更新佣金和工资所有员工都使用包装上的功能。有可能吗?

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;

3 个答案:

答案 0 :(得分:1)

您正在使用函数,因此它会重新调整值。您必须按照以下步骤捕获过程中的值:

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;

答案 1 :(得分: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,您只能处理一条记录。

答案 2 :(得分: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;