从 PL/SQL 关联数组中的元素获取不同的值

Posted

技术标签:

【中文标题】从 PL/SQL 关联数组中的元素获取不同的值【英文标题】:Get Distinct Value from an Element in a PL/SQL Associative Array 【发布时间】:2017-07-12 20:28:39 【问题描述】:

假设我有一张表XX_TABLE_SAMPLE,记录如下:

TAB_ID  BATCH_NAME  EMP_NO  EMP_NAME    STATUS      SALARY  CATEGORY
------  ----------  ------  --------    --------    ------- ------------
1       BATCH_A     1       Jared       Active      1000    (NULL)
2       BATCH_A     2       Siege       Active      3000    (NULL)
3       BATCH_A     45      James       Suspended   2000    (NULL)
4       BATCH_B     67      Harry       Active      100     (NULL)
5       BATCH_B     99      Pikachu     Active      10000   (NULL)
6       BATCH_x     100     Eren        Suspended   4000    (NULL)

我有如下的 PL/SQL 块(请注意 cmets):

declare

    cursor emp_cur is
    select  *
    from    XX_TABLE_SAMPLE
    where   status = 'Active';

    type emp_cur_type is table of XX_TABLE_SAMPLE%rowtype index by pls_integer;
    emp_rec emp_cur_type;

begin

    open    emp_cur;
    fetch   emp_cur
    bulk collect
    into    emp_rec;
    close   emp_cur;

    /*  do some pre-processing here via another stored procedure
        but the problem is, it has a parameter of p_batch_name, not a type of associative array

        for i in emp_rec.first..emp_rec.last loop
            pay_pkg.validate_pay (p_batch_name => emp_rec(i).p_batch_name);
        end;    
        -- the problem with this is that it will loop 4 times (twice each for BATCH_A and BATCH_B)
           when it should only get the 2 batch names (BATCH_A and BATCH_B)        
    */

    -- then check the salary of the emp and update the associative array    
    for i in emp_rec.first..emp_rec.last loop

        if emp_rec(i).salary > 200 and emp_rec(i).salary < 3000 then

            emp_rec(i).CATEGORY = 'Manager';

        end if;

    end loop;    

    forall i in emp_rec.first..emp_rec.last 
    update  XX_TABLE_SAMPLE
    set     CATEGORY = emp_rec(i).CATEGORY 
    where   TAB_ID   = emp_rec(i).TAB_ID;

end;

这样,我想在关联数组中获取元素 Batch_Name 的不同值 然后将其传递给存储过程pay_pkg.validate_pay

关于如何在不声明另一个显式光标的情况下实现这一目标的任何想法?

【问题讨论】:

能否请您告诉我们您需要的数组结果是什么? @JuanCarlosOropeza,关联数组将填充“活动”状态的记录(4 行)。但是,在我将调用pay_pkg.validate_pay 的部分中,我只需要从 1 列 (Batch_Name) 中获取 2 行(“BATCH_A”和“BATCH_B”) Migs 问题是如果您不提供所需的结果,我没有时间尝试破译您的代码所做的事情。我的建议是简化问题并专注于你不能做的事情。是查询吗? ,是创建一个数组吗?因为我不认为你需要一个光标。 【参考方案1】:

在我看来,您似乎在考虑不必要的复杂解决方案。我认为您的示例可以简化为以下需要零 PL/SQL 数据结构的解决方案(r 是隐式记录类型,但编译器会为您制作!)。

顺便说一句,PL/SQL 中没有必要害怕游标。

declare
  -- a dummy placeholder for the "tricky" subprogram
  procedure validate_pay(p_batch_name in varchar2) is begin null; end;
begin
  for r in (select distinct batch_name
              from xx_sample_data
             where status = 'Active')
  loop
    validate_pay(p_batch_name => r.batch_name);
  end loop;

  update xx_sample_data set
   category = 'Manager'
  where status = 'Active'
    and salary between 201 and 2999
  ;
end;
/

【讨论】:

只是一个提示,您假设薪水是一个整数以简化&gt; &lt; 条件,但我怀疑情况是否如此。 @JuanCarlosOropeza 是的,你是对的。我把它作为 OP 的练习。【参考方案2】:

也许是你没有说的其他东西,但如果你需要"BATCH_A", "BATCH_B"

为什么不直接使用:

SELECT DISTINCT BATCH_NAME  
FROM XX_TABLE_SAMPLE 
WHERE status = 'Active'
  AND salary > 200 
  AND salary < 3000

【讨论】:

这就是我要问的情况。是否可以只使用数组子集的不同值,而不必显式声明它们? 我不知道怎么做。你有一套,现在需要另一套。您可以循环第一组并删除重复项,但为此只需从头开始创建一组。创建两个集合有什么问题?【参考方案3】:

如果您在 oracle 12 上,还有另一种方法。

但这涉及从关联数组中进行选择

见 Select from PLSQL Associative array?

【讨论】:

以上是关于从 PL/SQL 关联数组中的元素获取不同的值的主要内容,如果未能解决你的问题,请参考以下文章

PL/SQL集合(table)嵌套表操作实例讲解实例

SQL记录-PLSQL集合

从 PL/SQL 中的过程返回值数组

PL/SQL 关联数组验证索引是不是存在

在 PL/SQL 中重置关联数组?

更新另一列时,使用列名作为 PL/SQL 关联数组的键