Я хотел бы создать переменную массива в памяти, которая может использоваться в моем коде PL/SQL. Я не могу найти какие-либо коллекции в Oracle PL/SQL, которые используют чистую память, все они, похоже, связаны с таблицами. Я хочу сделать что-то подобное в моем синтаксисе PL/SQL (С#):
string[] arrayvalues = new string[3] {"Matt", "Joanne", "Robert"};
Edit: Oracle: 9i
Вы можете использовать VARRAY для массива фиксированного размера:
declare
type array_t is varray(3) of varchar2(10);
array array_t := array_t('Matt', 'Joanne', 'Robert');
begin
for i in 1..array.count loop
dbms_output.put_line(array(i));
end loop;
end;
Или TABLE для неограниченного массива:
...
type array_t is table of varchar2(10);
...
Слово "таблица" здесь не имеет ничего общего с таблицами базы данных, смутно. Оба метода создают массивы в памяти.
С любым из них вам нужно как инициализировать, так и расширять коллекцию перед добавлением элементов:
declare
type array_t is varray(3) of varchar2(10);
array array_t := array_t(); -- Initialise it
begin
for i in 1..3 loop
array.extend(); -- Extend it
array(i) := 'x';
end loop;
end;
Первый индекс равен 1 не 0.
my_array(0) := 'some string';
Вы можете просто объявить DBMS_SQL.VARCHAR2_TABLE для хранения массива переменной длины в памяти, проиндексированного BINARY_INTEGER:
DECLARE
name_array dbms_sql.varchar2_table;
BEGIN
name_array(1) := 'Tim';
name_array(2) := 'Daisy';
name_array(3) := 'Mike';
name_array(4) := 'Marsha';
--
FOR i IN name_array.FIRST .. name_array.LAST
LOOP
-- Do something
END LOOP;
END;
Вы можете использовать ассоциативный массив (обычно называемый PL/SQL-таблицами), поскольку он является массивом в памяти.
DECLARE
TYPE employee_arraytype IS TABLE OF employee%ROWTYPE
INDEX BY PLS_INTEGER;
employee_array employee_arraytype;
BEGIN
SELECT *
BULK COLLECT INTO employee_array
FROM employee
WHERE department = 10;
--
FOR i IN employee_array.FIRST .. employee_array.LAST
LOOP
-- Do something
END LOOP;
END;
Ассоциативный массив может содержать любые типы записей.
Надеюсь, что это поможет, Олли.
VALUE_ERROR
когда коллекция пуста. Я бы предложил использовать FOR i IN 1 .. employee_array.COUNT
в этом случае
Другим решением является использование коллекции Oracle в виде Hashmap:
declare
-- create a type for your "Array" - it can be of any kind, record might be useful
type hash_map is table of varchar2(1000) index by varchar2(30);
my_hmap hash_map ;
-- i will be your iterator: it must be of the index type
i varchar2(30);
begin
my_hmap('a') := 'apple';
my_hmap('b') := 'box';
my_hmap('c') := 'crow';
-- then how you use it:
dbms_output.put_line (my_hmap('c')) ;
-- or to loop on every element - it a "collection"
i := my_hmap.FIRST;
while (i is not null) loop
dbms_output.put_line(my_hmap(i));
i := my_hmap.NEXT(i);
end loop;
end;
Вы также можете использовать oracle defined collection
DECLARE
arrayvalues sys.odcivarchar2list;
BEGIN
arrayvalues := sys.odcivarchar2list('Matt','Joanne','Robert');
FOR x IN ( SELECT m.column_value m_value
FROM table(arrayvalues) m )
LOOP
dbms_output.put_line (x.m_value||' is a good pal');
end loop;
END;
Я бы использовал массив in-memory. Но с улучшением .COUNT
, предложенным uziberia:
DECLARE
TYPE t_people IS TABLE OF varchar2(10);
INDEX BY PLS_INTEGER;
arrayvalues t_people;
BEGIN
SELECT *
BULK COLLECT INTO arrayvalues
FROM (select 'Matt' m_value from dual union all
select 'Joanne' from dual union all
select 'Robert' from dual
)
;
--
FOR i IN 1 .. arrayvalues.COUNT
LOOP
dbms_output.put_line(arrayvalues(i)||' is my friend');
END LOOP;
END;
Другим решением было бы использовать Hashmap, например @Jchomel здесь
Примечание:
С Oracle 12c вы можете даже массивы запросов прямо сейчас!