【问题标题】:PL/SQL Cursor and Array of different sizePL/SQL 游标和不同大小的数组
【发布时间】:2016-08-31 08:55:05
【问题描述】:

我想将 游标 的内容存储在关联 array 中(按 binary_integer 的表索引)。但在同一个数组中,我还想存储一个附加变量,比如布尔值。

我的游标每行有 n 个元素,并且数组被定义为有 n+1 个元素(n 与 cursorelements 具有相同的 %type),最后一个是布尔值。

我想要的是这样的

for cursorrow in cursor(...) 
loop
  array(row i) := cursorrow, boolean_variable;
end loop;

|1|2|...|n|n+1| := |1|2|...|n|, |1|

不幸的是,我无法让它工作。 有人知道怎么做吗?

【问题讨论】:

  • 创建一个记录..然后创建一个类型的记录并存储它。
  • 如果我做对了,那么这可以通过两种方式完成: 1. 记录有两个字段,一个是行类型,另一个是附加变量。在这种情况下,我失去了对各个列字段(如 cursor.field1 --> array.field1)的访问权限,这对进一步的程序来说是致命的。 2. 我必须(声明和)自己分配每个字段值。这是应该工作的,但我希望它可以做得更优雅。非常感谢您的快速回复!

标签: arrays oracle plsql cursor


【解决方案1】:

如何定义由%rowtype 记录和布尔值组成的复合记录类型?

测试设置:

create table demo_table
( some_id integer primary key
, some_name varchar2(30) not null unique
, some_type varchar2(10) not null );

insert all
    into demo_table values (1, 'One', 'X' )
    into demo_table values (2, 'Two', 'Y' )
    into demo_table values (3, 'Three', 'Z' )
select * from dual;

测试: (编辑:在循环中添加了dbms_output 消息)

declare
    subtype demo_rectype is demo_table%rowtype;

    type demo_rec is record
    ( details demo_rectype
    , somecheck boolean );

    type demo_tt is table of demo_rec index by pls_integer;
    t_demo demo_tt;

    cursor c_demo is select * from demo_table;
begin
    for r in c_demo
    loop
        t_demo(c_demo%rowcount).details := r;
        t_demo(c_demo%rowcount).somecheck := dbms_random.value < 0.5;

        dbms_output.put_line
        ( t_demo(c_demo%rowcount).details.some_name || ': ' ||
          case t_demo(c_demo%rowcount).somecheck
              when true then 'TRUE'
              when false then 'FALSE'
              else 'NULL'
          end );
    end loop;

    dbms_output.new_line();
    dbms_output.put_line('Array t_demo contains ' || t_demo.count || ' items.');
end;

输出:

One: FALSE
Two: FALSE
Three: TRUE

Array t_demo contains 3 items.

【讨论】:

  • @william..好代码,出于好奇,如何在此处打印光标(每条记录)的值。
  • 我认为这是问题所在。当然,这些值已存储。但是现在,“详细信息”中的字段不能再单独处理了。 (前提是我没有弄错)
  • 我已经用一些例子更新了我的答案。基本上你可以用你输入的方式读回它,即array(index).record.field。如果在游标循环之外,您可以将c_demo%rowcount 替换为一个变量(通常按约定命名为i)。
  • 所以实际上寻址是通过在限定名称中添加一个新级别来工作的。这很容易而且实际上很明显,但我没有明白。谢谢@WilliamRobertson!换句话说:假设我有一个带有归档 a、b 和 c 的 Record rec。我可以通过写rec.a 和rec.b 来处理a 和b。如果 c 包含带有 x 和 y 列的 %rowtype 结构,我可以使用 rec.c.x 和 rec.c.y 来处理它们。再一次,现在我看到了,这是非常明显的。再次感谢大家的帮助!
【解决方案2】:

由于记录类型与表结构(即布尔值)相差1个字段,因此您不能在1个赋值语句中将光标行分配给记录类型。您需要为每个表格列单独执行此操作:

for cursorrow in cursor(...) 
loop
  array(row i).col1 := cursorrow.col1;
  array(row i).col2 := cursorrow.col2;
  ...
  array(row i).coln := cursorrow.coln;
  array(row i).boolean_variable := some_boolean_value;
end loop;

【讨论】:

  • 谢谢。我希望这不是答案,但很高兴知道没有其他办法!
【解决方案3】:

如 cmets 中所述,您可以创建记录并执行此操作。您可以使用以下过程来实现您的要求。

create or replace procedure proc_test
as

  cursor cur_tab is 
   select a  --have selected only 1 column..you can choose many
    from test;

  TYPE  var_temp  IS TABLE OF cur_tab%ROWTYPE INDEX BY PLS_INTEGER;
  v_var              var_temp; 

 /**You can add columns selected in you cursor here in your record****/
 TYPE abc IS RECORD
  (
   id          varchar2(100), 
   orig_name   boolean      
   );

  TYPE  xx IS TABLE OF abc ;

  -- initialization of record
  v_xx    xx := xx() ;  

  t   boolean:=TRUE;    

 begin


  open cur_tab;

   fetch cur_tab bulk collect into v_var;

  close cur_tab;

  for i in 1..v_var.count
   loop

     v_xx.extend;

     v_xx(i).id := v_var(i).a;
     v_xx(i).orig_name := t;

      dbms_output.put_line (v_xx(i).id ||'----'||sys.diutil.bool_to_int(v_xx(i).orig_name));

     ---OR

      dbms_output.put_line (v_xx(i).id ||'----'||case when v_xx(i).orig_name = true then 'TRUE' ELSE 'FALSE' end );

   end loop;

  exception
  when others then 
  null;

 end;   

呼叫:

execute proc_test;

【讨论】:

  • 感谢您的详细解答。如果我猜对了,我仍然需要分别调用光标的每个字段/列。在这种情况下,像上面说明的 Martin Schapendonk 那样分配每个字段/列应该没有任何改进。对吗?
  • 是的..如果你需要它。或者您可以通过创建表的子类型然后将子类型用于记录列来进一步复杂化它。威廉解释了这一点。
  • @Rekisyhp..不确定 Martin 展示作业的方式是否可行。!!你试过了吗?
  • 是的,这就是我目前的解决方案。但由于我已经有几列但只想添加一个,我希望找到更优雅的东西。
  • 我只是不明白他是如何将最后一个布尔变量分配给数组的,如果这对你来说是最好的解决方案,请继续。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-17
  • 2021-06-23
  • 1970-01-01
  • 2012-03-27
  • 2012-04-28
  • 1970-01-01
相关资源
最近更新 更多