2016-08-31 5 views
0

Я хочу сохранить содержимое курсора в ассоциативном массиве (указатель таблицы по binary_integer). Но в том же массиве я также хочу сохранить дополнительную переменную , скажем, логическую.PL/SQL курсор и массив разного размера

Мой курсор имеет n элементов в строке и массив имеет n + 1 элементов (n с тем же% -ным типом, что и cursorelements), последний из которых является булевым.

Что я whant что-то вроде этого

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

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

К сожалению, я не могу заставить его работать. Кто-нибудь знает, как это сделать?

+0

Создать record..and затем создать тип, который записывает и хранит его. – XING

+0

Если я правильно понял, это можно было бы сделать двумя способами: 1. В записях есть два поля, один - тип строки, другой - дополнительная. В этом случае я теряю доступ к отдельным полям collumn (например, cursor.field1 -> array.field1), что является фатальным для дальнейшей программы. 2. Я должен (объявить и) присваивать каждое значение поля самостоятельно. Это то, что должно работать, но я надеялся, что это можно сделать более элегантным. Большое спасибо, однако, за быстрый ответ! – Rekisyhp

ответ

0

Как об определении составного типа записи, состоящий из %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; 

Тест: (Edit: добавлена ​​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. 
+0

@ william..Nice code, спрашивая из любопытства, как распечатать значения курсора (каждая запись) здесь. – XING

+0

Я думаю, что это проблема. Значения сохраняются, конечно. Но теперь поля в «деталях» больше не могут быть рассмотрены отдельно. (При условии, что я не ошибся) – Rekisyhp

+0

Я обновил свой ответ несколькими примерами. В принципе, вы можете прочитать его так же, как вы его ввели, т. Е. 'Array (index) .record.field'. Если вне цикла курсора вы замените 'c_demo% rowcount' переменной (обычно называемой' i' по соглашению). –

0

Поскольку тип записи отличается от 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; 
+0

Спасибо. Это то, на что я надеялся, не будет ответом, но хорошо знать, что другого пути нет! – Rekisyhp

0

Как уже упоминалось в комментариях, вы можете создать запись и сделать это. Вы можете использовать приведенную ниже процедуру для достижения своих требований.

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; 
+0

Благодарим вас за подробный ответ. Если я получу вас правильно, мне все равно придется вызывать каждое поле/столбец курсора отдельно. В этом случае не должно быть улучшения, чтобы просто назначить каждое поле/столбец таким образом, как показано на примере Мартина Шапендонка. Справа? – Rekisyhp

+0

Да .. если вам это нужно. Или вы можете еще больше усложнить его, сделав подтип таблицы, а затем используя подтип в столбце записи. Уильям объяснил это. – XING

+0

@ Rekisyhp..Не уверен, что Мартин показал, что назначение будет работать. !! Твоя попытка. – XING

Смежные вопросы