Usando Matrizes Associativas
Um array associativo é um tipo de conjunto.
Consulte também:
Para obter mais informações sobre as coleções:
Sobre Coleções
Uma coleção abrange uma variável composta PL/SQL que armazena elementos do mesmo tipo em uma ordem especificada, semelhante a uma matriz unidimensional. Os componentes internos de uma coleção são chamados elementos. Cada elemento tem um subscript exclusivo que identifica sua posição na coleta.
Para acessar um elemento de coleta, use notação de subscrito : collection_name(element_subscript).
Você pode tratar elementos de coleta·como variáveis escalares. Você também pode passar coleções inteiras como parâmetros do subprograma (se o subprograma de envio e recebimento não for um subprograma independente).
Um método de cobrança é um subprograma PL/SQL integrado que retorna informações sobre uma coleção ou opera em uma coleção. Para chamar um método de coleta, use notação de ponto: collection_name.method_name. Por exemplo, collection_name.COUNT retorna o número de elementos da coleção.
O PL/SQL tem três tipos de coleta:
-
Arrays associativos (anteriormente chamados de "tabelas PL/SQL" ou "tabelas indexadas")
-
Tabelas aninhadas
-
Matrizes variáveis (varrays)
Este documento explica apenas arrays associativos.
Consulte também:
-
Referência de Linguagem PL/SQL do Oracle Database para mais informações sobre tipos de coleta PL/SQL
-
Referência de Linguagem PL/SQL do Oracle Database para mais informações sobre métodos de coleta
Sobre Arrays Associativos
Um array associativo é um conjunto ilimitado de pares de chave/valor. Cada par é exclusivo e atua como subscript do elemento que contém o valor correspondente. Assim, você pode acessar elementos sem conhecer suas posições no array e sem percorrer o array.
O tipo de dados da chave pode ser PLS_INTEGER ou VARCHAR2 (comprimento).
Se o tipo de dados da chave for PLS_INTEGER e a matriz associativa for indexada por inteiro e for densa (ou seja, não tiver lacunas entre elementos), todos os elemento entre o primeiro e último elemento serão definidos e terão um valor (que pode ser NULL).
Se o tipo de chave for VARCHAR2 (comprimento), a matriz associativa será indexada por string (de caracteres de tamanho) e esparsa; ou seja, poderá haver lacunas entre elementos.
Ao percorrer um array associativo denso, você não precisará se importar com as lacunas entre os elementos; ao percorrer um array associativo esparso, você o faz.
Para atribuir um valor a um elemento de matriz associativa, você pode usar um operador de atribuição:
array_name(key) := value
Se a chave não estiver no array, a instrução de atribuição adicionará o par chave-valor ao array. Caso contrário, a instrução alterará o valor de array_name(key) para valor.
Os arrays associativos são úteis para armazenar dados temporariamente. Eles não usam o espaço em disco ou operações de rede exigidos pelas tabelas. No entanto, como os arrays associativos são destinados ao armazenamento temporário, não é possível manipulá-los com instruções DML.
Se você declarar um array associativo em um pacote e atribuir valores à variável no corpo do pacote, o array associativo existirá durante a vida útil da sessão do banco de Dados. Caso contrário, ele existirá durante a vigência do subprograma no qual você o declara.
Consulte também: Referência de Linguagem PL/SQL do Oracle Database para mais informações sobre arrays associativos
Declarando Arrays Associativos
Para declarar uma matriz associativa, declare um tipo de matriz associativa e, em seguida, declare uma variável desse tipo.
O código a seguir mostra a sintaxe mais simples:
TYPE array_type IS TABLE OF element_type INDEX BY key_type;
array_name array_type;
Uma maneira eficiente de declarar um array associativo é com um cursor, usando o procedimento a seguir. O procedimento usa cada instrução necessária em sua forma mais simples, mas fornece referências a sua sintaxe complexa.
Para usar um cursor para declarar um array associativo:
-
Na parte declarativa:
-
Declare o cursor:
CURSOR cursor_name IS query;Para obter a sintaxe completa da declaração de cursor declarada, consulte Referência de Linguagem PL/SQL do Oracle Database.
-
Declare o·tipo de array associativo:
TYPE array_type IS TABLE OF cursor_name%ROWTYPE INDEX BY { PLS_INTEGER | VARCHAR2 length }Para obter a sintaxe completa da declaração do tipo de array associativo, consulte Referência de Linguagem PL/SQL do Oracle Database.
-
Declare uma variável de·array associativo desse tipo:
array_name array_type;Para obter a sintaxe completa da declaração da variável, consulte Referência da Linguagem PL/SQL do Oracle Database.
-
Exemplo 5-9 usa o procedimento anterior para declarar dois arrays associativos, employees_jobs e jobs_ e, em seguida, declara um terceiro array associativo, job_titles, sem usar um cursor. Os dois primeiros arrays são indexados por número inteiro; o terceiro é indexado por string.
Observação: A cláusula ORDER BY na declaração employees_jobs_cursor determina a ordem de armazenamento dos elementos da matriz associativa employee_jobs.
Exemplo 5-9 Declarando Matrizes Associativas
DECLARE
-- Declare cursor:
CURSOR employees_jobs_cursor IS
SELECT FIRST_NAME, LAST_NAME, JOB_ID
FROM EMPLOYEES
ORDER BY JOB_ID, LAST_NAME, FIRST_NAME;
-- Declare associative array type:
TYPE employees_jobs_type IS TABLE OF employees_jobs_cursor%ROWTYPE
INDEX BY PLS_INTEGER;
-- Declare associative array:
employees_jobs employees_jobs_type;
-- Use same procedure to declare another associative array:
CURSOR jobs_cursor IS
SELECT JOB_ID, JOB_TITLE
FROM JOBS;
TYPE jobs_type IS TABLE OF jobs_cursor%ROWTYPE
INDEX BY PLS_INTEGER;
jobs_ jobs_type;
-- Declare associative array without using cursor:
TYPE job_titles_type IS TABLE OF JOBS.JOB_TITLE%TYPE
INDEX BY JOBS.JOB_ID%TYPE; -- jobs.job_id%type is varchar2(10)
job_titles job_titles_type;
BEGIN
NULL;
END;
/
Consulte também:
-
Referência de Linguagem PL/SQL do Oracle Database para sintaxe de declaração de matriz associativa
Preenchendo Matrizes Associativas
A maneira mais eficiente de preencher uma matriz associativa densa é geralmente com uma instrução SELECT com uma cláusula BULK COLLECT INTO.
Observação: Se um array associativo denso for tão grande que uma instrução SELECT retornaria um conjunto de resultados muito grande para caber na memória, não use uma instrução SELECT. Em vez disso, preencha a matriz com um cursor e a instrução FETCH com as cláusulas BULK COLLECT INTO e LIMIT. Para obter informações sobre como usar a instrução FETCH com a cláusula BULK COLLECT INTO, consulte Oracle Database PL/SQL Language Reference.
Você não pode usar uma instrução SELECT para preencher uma matriz associativa esparsa (como job_titles em "Declaring Associative Arrays"). Em vez disso, use uma instrução de designação em uma instrução de loop. Para obter informações sobre instruções do loop, consulte "Controlando o Fluxo do Programa". Exemplo 5-10 usa instruções SELECT para preencher os arrays associativos employees_jobs e jobs_, que são indexados por inteiro. Em seguida, ele usa uma instrução da atribuição dentro de uma instrução FOR LOOP para preencher o job_titles da matriz associativa, que é indexado por string.
Exemplo 5-10 Preenchendo Matrizes Associativas
-- Declarative part from Example 5-9 goes here.
BEGIN
-- Populate associative arrays indexed by integer:
SELECT FIRST_NAME, LAST_NAME, JOB_ID BULK COLLECT INTO employees_jobs
FROM EMPLOYEES ORDER BY JOB_ID, LAST_NAME, FIRST_NAME;
SELECT JOB_ID, JOB_TITLE BULK COLLECT INTO jobs_ FROM JOBS;
-- Populate associative array indexed by string:
FOR i IN 1..jobs_.COUNT() LOOP
job_titles(jobs_(i).job_id) := jobs_(i).job_title;
END LOOP;
END;
/
Consulte Também: "Sobre Cursores"
Percorrendo Matrizes Associativas Densas
Um array associativo denso (indexado por inteiro) não tem lacunas entre elementos - cada elemento entre o primeiro e último elemento é definido e tem um valor (que pode ser NULO).
Você pode percorrer um array denso com uma instrução FOR LOOP, como no Exemplo 5-11.
Quando inserido na parte executável do Exemplo 5-10, após o código que preenche a matriz employees_jobs, a instrução FOR LOOP no Exemplo 5-11 imprime os elementos da matriz employees_jobs na ordem em que foram armazenados. Sua ordem de armazenamento foi determinada pela cláusula ORDER BY na declaração employees_jobs_cursor, que foi usada para declarar employees_jobs (consulte Exemplo 5-9).
O limite superior da instrução FOR LOOP, employees_jobs.COUNT, chama um método da coleta que retorna o número de elementos na matriz. Para obter mais informações sobre COUNT, consulte Referência de Linguagem PL/SQL do Oracle Database.
Exemplo 5-11 Percorrendo uma Matriz Associativa Densa
-- Code that populates employees_jobs must precede this code:
FOR i IN 1..employees_jobs.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(
RPAD(employees_jobs(i).first_name, 23) ||
RPAD(employees_jobs(i).last_name, 28) || employees_jobs(i).job_id);
END LOOP;
Resultado:
William Gietz AC_ACCOUNT
Shelley Higgins AC_MGR
Jennifer Whalen AD_ASST
Steven King AD_PRES
Lex De Haan AD_VP
Neena Kochhar AD_VP
John Chen FI_ACCOUNT
...
Jose Manuel Urman FI_ACCOUNT
Nancy Greenberg FI_MGR
Susan Mavris HR_REP
David Austin IT_PROG
...
Valli Pataballa IT_PROG
Michael Hartstein MK_MAN
Pat Fay MK_REP
Hermann Baer PR_REP
Shelli Baida PU_CLERK
...
Sigal Tobias PU_CLERK
Den Raphaely PU_MAN
Gerald Cambrault SA_MAN
...
Eleni Zlotkey SA_MAN
Ellen Abel SA_REP
...
Clara Vishney SA_REP
Sarah Bell SH_CLERK
...
Peter Vargas ST_CLERK
Adam Fripp ST_MAN
...
Matthew Weiss ST_MAN
Percorrendo Matrizes Associativas Dispersas
Uma array associativa esparsa (indexada por string) pode ter lacunas entre elementos.
Você pode percorrê-lo com uma instrução WHILE LOOP, como no Exemplo 5-12.
Para executar o código no Exemplo 5-12, que imprime os elementos da matriz job_titles, execute as seguintes etapas:
-
No final da parte declarativa do Exemplo 5-9, insira esta declaração da variável:
i jobs.job_id%TYPE; -
Na parte executável do Exemplo 5-10, após o código que preenche o array job_titles, insira o código do Exemplo 5-12.
Exemplo 5-12 Percorrendo uma Matriz Associativa Esparsa
/* Declare this variable in declarative part:
i jobs.job_id%TYPE;
Add this code to the executable part,
after code that populates job_titles:
*/
i := job_titles.FIRST;
WHILE i IS NOT NULL LOOP
DBMS_OUTPUT.PUT_LINE(RPAD(i, 12) || job_titles(i));
i := job_titles.NEXT(i);
END LOOP;
Resultado:
AC_ACCOUNT Public Accountant
AC_MGR Accounting Manager
AD_ASST Administration Assistant
AD_PRES President
AD_VP Administration Vice President
FI_ACCOUNT Accountant
FI_MGR Finance Manager
HR_REP Human Resources Representative
IT_PROG Programmer
MK_MAN Marketing Manager
MK_REP Marketing Representative
PR_REP Public Relations Representative
PU_CLERK Purchasing Clerk
PU_MAN Purchasing Manager
SA_MAN Sales Manager
SA_REP Sales Representative
SH_CLERK Shipping Clerk
ST_CLERK Stock Clerk
ST_MAN Stock Manager
O Exemplo 5-12 inclui duas invocações de método de coleta, job_titles.FIRST e job_titles.NEXT(i). job_titles.FIRST retorna o primeiro elemento de job_titles e job_titles.NEXT(i) retorna o subscrito que é bem-sucedido i. Para obter mais informações sobre PRIMEIRO, consulte Referência de Linguagem PL/SQL do Oracle Database. Para obter mais informações sobre PRÓXIMO, consulte Oracle Database PL/SQL Language Reference.