【问题标题】:How do I resolve this procedure in PL/SQL如何在 PL/SQL 中解决此过程
【发布时间】:2020-04-29 11:02:39
【问题描述】:

我被 PL/SQL 程序的顺序搞砸了 我需要做一个接收部门编号、薪水和百分比作为参数的程序;并提高电话中指定部门的所有员工的工资。增加的金额将是电话中指示的百分比或薪水(在每种情况下,以对员工更有利的为准)。 我有这个代码,但不起作用。

CREATE OR REPLACE PROCEDURE pujarSalari (numdept number,diners number,percentatge number)
AS
souapujar number(10);
CURSOR buscarnoms IS SELECT codi_emp FROM empleats WHERE codi_dept=numdept;
BEGIN
OPEN buscarnoms;
FETCH buscarnoms INTO souapujar;
WHILE buscarnoms%FOUND LOOP
IF (empleats.sou*(1+percentatge/100))>=(empleats.sou+diners) THEN
UPDATE empleats set empleats.sou=empleats.sou*(1+percentatge/100) where codi_emp=souapujar;
ELSE
UPDATE empleats set empleats.sou=empleats.sou+diners where codi_emp=souapujar;
END IF;
FETCH buscarnoms INTO souapujar;
END LOOP;
CLOSE buscarnoms;
END; 

错误码是

Procedure PUJARSALARI compilado

LINE/COL  ERROR
--------- -------------------------------------------------------------
9/1       PL/SQL: Statement ignored
9/14      PLS-00357: Table,View Or Sequence reference 'EMPLEATS.SOU' not allowed in this context
Errores: comprobar log de compilador

【问题讨论】:

  • 请提供示例数据、期望的结果以及您想要实现的逻辑的解释。

标签: sql oracle plsql


【解决方案1】:

您的 IF 语句引用了表格列。在 PL/SQL 中,我们只能引用变量(包括隐式游标)。 (这在嵌入式 SQL 语句之外。)

您有一个光标buscarnoms,它从empleats 中选择,但不包括您需要的所有列。因此,您必须更改光标投影,然后在代码中引用光标。

CREATE OR REPLACE PROCEDURE pujarSalari 
  (numdept number,
   diners number,
   percentatge number)
AS
  CURSOR buscarnoms IS 
    SELECT * 
    FROM empleats 
    WHERE codi_dept = numdept;
  souapujar buscarnoms%rowtype; -- inherits the projection of the cursor
BEGIN
  OPEN buscarnoms;
  FETCH buscarnoms INTO souapujar;
  WHILE buscarnoms%FOUND LOOP
    IF (souapujar.sou*(1+percentatge/100)) >= (souapujar.sou+diners) THEN
        UPDATE empleats 
        set empleats.sou = empleats.sou*(1+percentatge/100) 
        where codi_emp = souapujar.codi_emp;
    ELSE
      UPDATE empleats 
      set empleats.sou = empleats.sou+diners 
      where codi_emp = souapujar.codi_emp;
    END IF;
    FETCH buscarnoms INTO souapujar;
  END LOOP;
  CLOSE buscarnoms;
END; 

有几种方法可以简化此代码,例如将显式游标替换为隐式游标。甚至用基于集合的更新语句替换游标循环。但我已将代码尽可能接近原始代码,以突出显示问题的解决方案。


你说这是简化代码的几种方法。我怎样才能简化我的代码?

隐式游标:

CREATE OR REPLACE PROCEDURE pujarSalari 
  (numdept number,
   diners number,
   percentatge number)
AS
BEGIN
  FOR buscarnoms in (SELECT * 
                     FROM empleats 
                     WHERE codi_dept = numdept)
  LOOP
    IF (souapujar.sou*(1+percentatge/100)) >= (souapujar.sou+diners) THEN
        UPDATE empleats 
        set empleats.sou = empleats.sou*(1+percentatge/100) 
        where codi_emp = souapujar.codi_emp;
    ELSE
      UPDATE empleats 
      set empleats.sou = empleats.sou+diners 
      where codi_emp = souapujar.codi_emp;
    END IF;
  END LOOP;
END; 

基于集合:

CREATE OR REPLACE PROCEDURE pujarSalari 
  (numdept number,
   diners number,
   percentatge number)
AS
BEGIN

  UPDATE empleats 
  set    sou = greatest(empleats.sou + diners, 
                        empleats.sou * (1+percentatge/100) )
  where codi_dept = numdept;

END; 

【讨论】:

  • 你说的就是简化代码的几种方法。如何简化我的代码?
【解决方案2】:

嗯,这实际上是一个不同的问题,应该以这种方式提出。但是最大简化怎么样。将其简化为一条语句:

 create or replace procedure pujarsalari 
      (numdept     number,
       diners      number,
       percentatge number)
    as
    begin
        update empleats 
           set sou = greatest(sou*(1+percentatge/100), sou+diners)   
         where codi_dept = numdept;
    end  pujarsalari;

每日提示:在 SQL 中,不要再考虑单个行了。考虑一次而不是所有行的集合。

注意:未测试,因为您认为不适合发布样本数据和表格定义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-26
    • 2022-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多