【问题标题】:How to call a function within a procedure to update all records of a table on PLSQL?如何在过程中调用函数来更新 PLSQL 上表的所有记录?
【发布时间】:2016-12-07 22:33:58
【问题描述】:

我正在练习 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;

【问题讨论】:

  • 你的函数作为过程会更有意义。你还传入了employee_ids,所以它们应该是employees.employee_id%TYPE
  • 你到底想让comm_dal_upd做什么?是否应将规定的佣金和工资调整应用于所有员工?如果是这样,您的佣金和工资程序/函数应该接受 p_new_commp_new_sal 作为参数并使用它们而不是硬编码值。
  • 感谢您的回复。其实我认为你是对的,所以是否可以编写一个程序,然后使用 RETURNING 属性作为 comm_sal_upd 程序的参数?- com,_sal_upd 是一个使用 comm_upd 和 sal_upd 函数更新所有员工工资和佣金的程序。
  • 是的,但是p_new_commp_new_sal 参数是干什么用的?
  • 好吧,我已经创建了这些参数来分配所有员工的新工资和新佣金,但现在我明白了你的意思。不需要在程序中添加参数,因为工资和佣金条件在其他函数中!!!

标签: sql oracle plsql


【解决方案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;

【讨论】:

  • 是的,你是对的,但我不知道怎么做!!我将尝试使用您的代码,稍后将粘贴我的新代码。谢谢
  • 我已经在我的解决方案中给出了这个想法。逐行阅读。
【解决方案2】:

首先,有一些技巧可以改善您的功能。

当您可以进行一次查询时,您不需要进行两次查询。而不是

  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,您只处理一条记录。

【讨论】:

  • 感谢您的回复。你是对的,现在我对这个程序的代码有了一个想法。但关键是我需要使用功能制作程序。我现在就试试。
【解决方案3】:

我认为以下是您正在尝试做的事情。 (未经测试,可能有错误。)请注意,这是在 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;

【讨论】:

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