PL / SQL - Coleções

Neste capítulo, discutiremos as Coleções em PL / SQL. Uma coleção é um grupo ordenado de elementos com o mesmo tipo de dados. Cada elemento é identificado por um subscrito exclusivo que representa sua posição na coleção.

PL / SQL fornece três tipos de coleção -

  • Tabelas de indexação ou matriz associativa
  • Mesa aninhada
  • Matriz de tamanho variável ou Varray

A documentação Oracle fornece as seguintes características para cada tipo de coleção -

Tipo de coleção Número de Elementos Tipo de Subscrito Denso ou esparso Onde foi criado Pode ser atributo de tipo de objeto
Matriz associativa (ou índice por tabela) Sem limites String ou inteiro Ou Apenas em bloco PL / SQL Não
Mesa aninhada Sem limites Inteiro Começa denso, pode se tornar esparso Tanto no bloco PL / SQL quanto no nível do esquema sim
Matriz de tamanho variável (Varray) Limitado Inteiro Sempre denso Tanto no bloco PL / SQL quanto no nível do esquema sim

Já discutimos varray no capítulo 'PL/SQL arrays'. Neste capítulo, discutiremos as tabelas PL / SQL.

Ambos os tipos de tabelas PL / SQL, ou seja, as tabelas index-by e as tabelas aninhadas têm a mesma estrutura e suas linhas são acessadas usando a notação de subscrito. No entanto, esses dois tipos de tabelas diferem em um aspecto; as tabelas aninhadas podem ser armazenadas em uma coluna do banco de dados e as tabelas index-by não podem.

Índice por tabela

A index-by tabela (também chamada de associative array) é um conjunto de key-valuepares. Cada chave é única e é usada para localizar o valor correspondente. A chave pode ser um número inteiro ou uma string.

Uma tabela index-by é criada usando a seguinte sintaxe. Aqui, estamos criando umindex-by mesa chamada table_name, as chaves serão do subscript_type e os valores associados serão do element_type

TYPE type_name IS TABLE OF element_type [NOT NULL] INDEX BY subscript_type; 
 
table_name type_name;

Exemplo

O exemplo a seguir mostra como criar uma tabela para armazenar valores inteiros junto com nomes e posteriormente imprimir a mesma lista de nomes.

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; 
/

Quando o código acima é executado no prompt SQL, ele produz o seguinte resultado -

Salary of James is 78000 
Salary of Martin is 100000 
Salary of Minakshi is 75000 
Salary of Rajnish is 62000  

PL/SQL procedure successfully completed.

Exemplo

Os elementos de uma tabela index-by também podem ser um %ROWTYPE de qualquer tabela de banco de dados ou %TYPEde qualquer campo da tabela do banco de dados. O exemplo a seguir ilustra o conceito. Vamos usar oCUSTOMERS tabela armazenada em nosso banco de dados como -

Select * from customers;  

+----+----------+-----+-----------+----------+ 
| ID | NAME     | AGE | ADDRESS   | SALARY   | 
+----+----------+-----+-----------+----------+ 
|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 | 
|  2 | Khilan   |  25 | Delhi     |  1500.00 | 
|  3 | kaushik  |  23 | Kota      |  2000.00 | 
|  4 | Chaitali |  25 | Mumbai    |  6500.00 | 
|  5 | Hardik   |  27 | Bhopal    |  8500.00 | 
|  6 | Komal    |  22 | MP        |  4500.00 | 
+----+----------+-----+-----------+----------+

DECLARE 
   CURSOR c_customers is 
      select name from customers; 

   TYPE c_list IS TABLE of customers.Name%type INDEX BY binary_integer; 
   name_list c_list; 
   counter integer :=0; 
BEGIN 
   FOR n IN c_customers LOOP 
      counter := counter +1; 
      name_list(counter) := n.name; 
      dbms_output.put_line('Customer('||counter||'):'||name_lis t(counter)); 
   END LOOP; 
END; 
/

Quando o código acima é executado no prompt SQL, ele produz o seguinte resultado -

Customer(1): Ramesh  
Customer(2): Khilan  
Customer(3): kaushik     
Customer(4): Chaitali  
Customer(5): Hardik  
Customer(6): Komal  

PL/SQL procedure successfully completed

Mesas Aninhadas

UMA nested tableé como uma matriz unidimensional com um número arbitrário de elementos. No entanto, uma tabela aninhada difere de uma matriz nos seguintes aspectos -

  • Uma matriz tem um número declarado de elementos, mas uma tabela aninhada não. O tamanho de uma tabela aninhada pode aumentar dinamicamente.

  • Um array é sempre denso, ou seja, sempre possui subscritos consecutivos. Uma matriz aninhada é inicialmente densa, mas pode se tornar esparsa quando os elementos são excluídos dela.

Uma tabela aninhada é criada usando a seguinte sintaxe -

TYPE type_name IS TABLE OF element_type [NOT NULL]; 
 
table_name type_name;

Esta declaração é semelhante à declaração de um index-by mesa, mas não há INDEX BY cláusula.

Uma tabela aninhada pode ser armazenada em uma coluna do banco de dados. Ele também pode ser usado para simplificar as operações SQL, em que você associa uma tabela de coluna única a uma tabela maior. Uma matriz associativa não pode ser armazenada no banco de dados.

Exemplo

Os exemplos a seguir ilustram o uso de tabela aninhada -

DECLARE 
   TYPE names_table IS TABLE OF VARCHAR2(10); 
   TYPE grades IS TABLE OF INTEGER;  
   names names_table; 
   marks grades; 
   total integer; 
BEGIN 
   names := names_table('Kavita', 'Pritam', 'Ayan', 'Rishav', 'Aziz'); 
   marks:= grades(98, 97, 78, 87, 92); 
   total := names.count; 
   dbms_output.put_line('Total '|| total || ' Students'); 
   FOR i IN 1 .. total LOOP 
      dbms_output.put_line('Student:'||names(i)||', Marks:' || marks(i)); 
   end loop; 
END; 
/

Quando o código acima é executado no prompt SQL, ele produz o seguinte resultado -

Total 5 Students 
Student:Kavita, Marks:98 
Student:Pritam, Marks:97 
Student:Ayan, Marks:78 
Student:Rishav, Marks:87 
Student:Aziz, Marks:92  

PL/SQL procedure successfully completed.

Exemplo

Elementos de um nested table também pode ser um %ROWTYPEde qualquer tabela do banco de dados ou% TYPE de qualquer campo da tabela do banco de dados. O exemplo a seguir ilustra o conceito. Usaremos a tabela CUSTOMERS armazenada em nosso banco de dados como -

Select * from customers;  

+----+----------+-----+-----------+----------+ 
| ID | NAME     | AGE | ADDRESS   | SALARY   | 
+----+----------+-----+-----------+----------+ 
|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 | 
|  2 | Khilan   |  25 | Delhi     |  1500.00 | 
|  3 | kaushik  |  23 | Kota      |  2000.00 | 
|  4 | Chaitali |  25 | Mumbai    |  6500.00 | 
|  5 | Hardik   |  27 | Bhopal    |  8500.00 | 
|  6 | Komal    |  22 | MP        |  4500.00 | 
+----+----------+-----+-----------+----------+

DECLARE 
   CURSOR c_customers is  
      SELECT  name FROM customers;  
   TYPE c_list IS TABLE of customerS.No.ame%type; 
   name_list c_list := c_list(); 
   counter integer :=0; 
BEGIN 
   FOR n IN c_customers LOOP 
      counter := counter +1; 
      name_list.extend; 
      name_list(counter)  := n.name; 
      dbms_output.put_line('Customer('||counter||'):'||name_list(counter)); 
   END LOOP; 
END; 
/

Quando o código acima é executado no prompt SQL, ele produz o seguinte resultado -

Customer(1): Ramesh  
Customer(2): Khilan  
Customer(3): kaushik     
Customer(4): Chaitali  
Customer(5): Hardik  
Customer(6): Komal  

PL/SQL procedure successfully completed.

Métodos de coleta

A PL / SQL fornece os métodos de coleta integrados que tornam as coleções mais fáceis de usar. A tabela a seguir lista os métodos e suas finalidades -

S.No Nome e objetivo do método
1

EXISTS(n)

Retorna TRUE se o enésimo elemento em uma coleção existir; caso contrário, retorna FALSE.

2

COUNT

Retorna o número de elementos que uma coleção contém atualmente.

3

LIMIT

Verifica o tamanho máximo de uma coleção.

4

FIRST

Retorna os primeiros (menores) números de índice em uma coleção que usa os subscritos inteiros.

5

LAST

Retorna os últimos (maiores) números de índice em uma coleção que usa os subscritos inteiros.

6

PRIOR(n)

Retorna o número do índice que precede o índice n em uma coleção.

7

NEXT(n)

Retorna o número do índice que sucede ao índice n.

8

EXTEND

Acrescenta um elemento nulo a uma coleção.

9

EXTEND(n)

Acrescenta n elementos nulos a uma coleção.

10

EXTEND(n,i)

Anexos ncópias do i ésimo elemento para uma coleção.

11

TRIM

Remove um elemento do final de uma coleção.

12

TRIM(n)

Remove n elementos do final de uma coleção.

13

DELETE

Remove todos os elementos de uma coleção, definindo COUNT como 0.

14

DELETE(n)

Remove o nthelemento de uma matriz associativa com uma chave numérica ou uma tabela aninhada. Se a matriz associativa tiver uma chave de string, o elemento correspondente ao valor da chave será excluído. E sen é nulo, DELETE(n) faz nada.

15

DELETE(m,n)

Remove todos os elementos do intervalo m..nde uma matriz associativa ou tabela aninhada. E sem é maior que n ou se m ou n é nulo, DELETE(m,n) faz nada.

Exceções de coleção

A tabela a seguir fornece as exceções de coleção e quando elas são levantadas -

Exceção de coleção Criado em Situações
COLLECTION_IS_NULL Você tenta operar em uma coleção atomicamente nula.
NENHUM DADO ENCONTRADO Um subscrito designa um elemento que foi excluído ou um elemento inexistente de uma matriz associativa.
SUBSCRIPT_BEYOND_COUNT Um subscrito excede o número de elementos em uma coleção.
SUBSCRIPT_OUTSIDE_LIMIT Um subscrito está fora do intervalo permitido.
VALUE_ERROR Um subscrito é nulo ou não conversível para o tipo de chave. Esta exceção pode ocorrer se a chave for definida como umPLS_INTEGER intervalo, e o subscrito está fora desse intervalo.