Chciałbym utworzyć zmienną tablicową w pamięci, która może być używana w moim kodzie PL / SQL. Nie mogę znaleźć żadnych kolekcji w Oracle PL / SQL, które używają czystej pamięci, wszystkie wydają się być powiązane z tabelami. Chcę zrobić coś takiego w moim PL / SQL (składnia C #):
string[] arrayvalues = new string[3] {"Matt", "Joanne", "Robert"};
Edycja: Oracle: 9i
Odpowiedzi:
Możesz użyć VARRAY dla tablicy o stałym rozmiarze:
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;
Lub TABELA dla nieograniczonej tablicy:
Słowo „tabela” nie ma tu nic wspólnego z tabelami bazy danych, myląco. Obie metody tworzą tablice w pamięci.
W przypadku każdego z nich musisz zainicjować i rozszerzyć kolekcję przed dodaniem elementów:
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;
Pierwszy indeks to 1, a nie 0.
źródło
my_array(0) := 'some string';
array.extend();
czy EXTEND dodaje gniazdo do zwykłej tablicy ograniczonej? W takim przypadku ma już dynamiczny rozmiar, więc tabela (nieograniczona tablica) nie byłaby potrzebna.varray(3)
4 razy - pojawia się błąd „indeks poza limitem”.array.extend()
. Każde miejsce, w którym szukałem, nie pokazywało tego i było to najważniejsze w możliwości dodania więcej niż jednego elementu (z mojego zrozumienia, wciąż nowego dla tablic w SQL).Możesz po prostu zadeklarować DBMS_SQL.VARCHAR2_TABLE, aby przechowywać w pamięci tablicę o zmiennej długości indeksowaną przez 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;
Możesz użyć tablicy asocjacyjnej (nazywanej wcześniej tabelami PL / SQL), ponieważ jest to tablica w pamięci.
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;
Tablica asocjacyjna może zawierać dowolne typy rekordów.
Mam nadzieję, że to pomoże, Ollie.
źródło
VALUE_ERROR
pojawia się, gdy kolekcja jest pusta. Proponuję raczej użyćFOR i IN 1 .. employee_array.COUNT
w tym przypadkusys.odcivarchar2list
poniższym przykładzie ma tę zaletę, że masz również pod ręką konstruktora, np. do domyślnej inicjalizacji parametru funkcji:sys.odcivarchar2list('val1','val2')
Innym rozwiązaniem jest użycie Oracle Collection jako 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's 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's 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;
źródło
Możesz również użyć pliku
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;
Użyłbym tablicy w pamięci. Ale z
.COUNT
poprawą sugerowaną przez 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;
Innym rozwiązaniem byłoby użycie Hashmapy, takiej jak @Jchomel tutaj .
Uwaga:
Dzięki Oracle 12c możesz teraz bezpośrednio wysyłać zapytania do tablic !
źródło
Przykładowe programy w następujący sposób i dostępne pod linkiem również https://oracle-concepts-learning.blogspot.com/
plsql tabeli lub powiązanej tablicy.
DECLARE TYPE salary IS TABLE OF NUMBER INDEX BY VARCHAR2(20); salary_list salary; name VARCHAR2(20); BEGIN -- adding elements to the table salary_list('Rajnish') := 62000; salary_list('Minakshi') := 75000; salary_list('Martin') := 100000; salary_list('James') := 78000; -- printing the table name := salary_list.FIRST; WHILE name IS NOT null LOOP dbms_output.put_line ('Salary of ' || name || ' is ' || TO_CHAR(salary_list(name))); name := salary_list.NEXT(name); END LOOP; END; /
źródło