простой пример новичка с использованием VARRAY с хранимой процедурой JDBC и PL/SQL

Я пытаюсь создать простой пример, чтобы понять, как хранить, а затем извлекать данные (массив с плавающей запятой) из/в программу Java в базу данных Oracle (11,2 ГБ) с помощью хранимой процедуры PL/SQL на основе VARRAY.

Я изо всех сил старался собрать программу на Java, но может быть одна или две ошибки. Я также застрял в том, как написать код PL/SQL для записи, а затем прочитать VARRAY в/из базы данных. Любой совет будет принят во внимание.

Java-программа:

// create example array
double[] myArray = new double[3];
myArray[0] = 1.1;
myArray[1] = 2.2;
myArray[2] = 3.3;
...
// setup call to stored procedure using SQL92 syntax
cs = conn.prepareCall( "{call my_sproc (?,?)}" );
// set IN parameters
cs.setString(1, myArray);
// set OUT parameters
cs.registerOutParameter(2, Types.ARRAY, "my_array");
// execute
cs.execute();
// retrieve array 
double[] returnedArray = new double[3];
returnedArray = cs.getArray(2);
...

Хранимая процедура PL/SQL:

create or replace procedure my_sproc ( 
    input_array IN as VARRAY(3) of BINARY_FLOAT,
    output_array OUT as VARRAY(3) of BINARY_FLOAT )
as
begin

-- how to write input_array into any example table?

-- how to read input_array from example table and store in variable: output_array?

end my_sproc;

person ggkmath    schedule 22.03.2012    source источник


Ответы (1)


В PL/SQL довольно редко используется VARRAY, так как вы должны указать максимальную длину. Гораздо чаще используются коллекции на основе вложенных таблиц или ассоциативных массивов.

Если вы хотите использовать коллекции на основе VARRAY, вы можете сделать что-то вроде

create type float_array
    is varray(3) of binary_float;
/

create table foo (
  col1 number
);
/

create or replace procedure varray_proc( p_in_arr   in float_array,
                                         p_out_arr out float_array )
as
begin
  for i in 1 .. p_in_arr.count
  loop
    insert into foo( col1 )
      values( p_in_arr(i) );
  end loop;
  select col1*2
    bulk collect into p_out_arr
    from foo;
end;
/

Вы можете вызвать процедуру из PL/SQL

SQL> declare
  2    l_in_arr  float_array := float_array( 1.1, 2.2, 3.3 );
  3    l_out_arr float_array;
  4  begin
  5    varray_proc( l_in_arr,
  6                 l_out_arr );
  7    for i in 1 .. l_out_arr.count
  8    loop
  9      dbms_output.put_line( l_out_arr(i) );
 10    end loop;
 11  end;
 12  /
2.20000005E+000
4.4000001E+000
6.5999999E+000

PL/SQL procedure successfully completed.

Было бы гораздо более распространенным объявлять и использовать тип вложенной таблицы, который в конечном итоге выглядит почти точно так же, как код VARRAY, только без ограничения длины.

create type float_nt
    is table of binary_float;

create or replace procedure varray_proc( p_in_arr   in float_nt,
                                         p_out_arr out float_nt )
as
begin
  for i in 1 .. p_in_arr.count
  loop
    insert into foo( col1 )
      values( p_in_arr(i) );
  end loop;
  select col1*2
    bulk collect into p_out_arr
    from foo;
end;
/

Если вы хотите сохранить порядок элементов массива

create table bar (
  col1     number, 
  order_by number
);

create or replace procedure varray_proc( p_in_arr   in float_nt,
                                         p_out_arr out float_nt )
as
begin
  for i in 1 .. p_in_arr.count
  loop
    insert into bar( col1, order_by )
      values( p_in_arr(i), i );
  end loop;
  select col1*2
    bulk collect into p_out_arr
    from bar
   order by order_by;
end;
/
person Justin Cave    schedule 22.03.2012
comment
Спасибо, Джастин, в моем случае я всегда буду знать длину массива в Java, и меня не интересует какой-либо реляционный аспект массива (не нужно искать элемент в массиве и т. д.). Поэтому я подумал, что VARRAY минимизирует таблицы. Поскольку порядок элементов в массиве важен, должен ли приведенный выше код создать еще один столбец (например, order) для хранения порядка элементов в столбце? - person ggkmath; 22.03.2012
comment
@ggkmath - я обновил свой ответ. Использование вложенной таблицы выглядит практически так же, как использование VARRAY, только без жестко заданного ограничения. И я также показал пример хранения индекса. - person Justin Cave; 22.03.2012
comment
Замечательно, спасибо, Джастин! Если я знаю длину массива, было бы предпочтительнее использовать varray, а не вложенную таблицу, поскольку выделение памяти можно определить заранее? Или по какой-то причине предпочтительнее вложенная таблица? - person ggkmath; 22.03.2012
comment
@ggkmath - с точки зрения распределения памяти на самом деле нет никакой пользы - и varray, и вложенная таблица будут потреблять одинаковое количество оперативной памяти, если они имеют одинаковое количество элементов. Поскольку вложенные таблицы более гибкие, если размер когда-либо изменится в будущем или если вы не хотите объявлять кучу разных типов для массивов разного размера, большинство людей будут просто использовать вложенные таблицы везде. - person Justin Cave; 22.03.2012