Introdução
O Oracle 21c introduziu melhorias significativas nos controles de iteração de coleções e nas expressões qualificadas. Estas funcionalidades aprimoram a legibilidade do código, permitindo que os desenvolvedores expressem lógicas complexas de forma mais concisa e clara. Este artigo explorará em detalhes estas novas características, fornecendo exemplos práticos e considerações de uso.
Controles de Iteração de Coleções
O Oracle 21c introduziu três novos controles de iteração de coleções: VALUES OF, INDICES OF e PAIRS OF. Cada um destes oferece uma maneira única de interagir com os elementos de uma coleção.
1. VALUES OF
O controle VALUES OF permite iterar diretamente sobre os valores de uma coleção.
Exemplo:
1 2 3 4 5 6 7 8 9 10 11 |
DECLARE TYPE tab_type IS TABLE OF PLS_INTEGER INDEX BY PLS_INTEGER; v_tab tab_type; BEGIN v_tab(1) := 10; v_tab(2) := 20; v_tab(3) := 30; v_tab(5) := 50; DBMS_OUTPUT.PUT_LINE('Valores da coleção:'); FOR v IN VALUES OF v_tab LOOP DBMS_OUTPUT.PUT_LINE('valor = ' || v); END LOOP; END; |
Saída:
1 2 3 4 5 6 |
Valores da coleção: valor = 10 valor = 20 valor = 30 valor = 50 |
2. INDICES OF
O controle INDICES OF permite iterar sobre os índices de uma coleção. Este é particularmente útil quando você precisa acessar ou manipular os índices diretamente.
Exemplo:
1 2 3 4 5 6 7 8 9 10 11 |
DECLARE TYPE tab_type IS TABLE OF PLS_INTEGER INDEX BY PLS_INTEGER; v_tab tab_type; BEGIN v_tab(1) := 10; v_tab(2) := 20; v_tab(3) := 30; v_tab(5) := 50; DBMS_OUTPUT.PUT_LINE('Índices da coleção:'); FOR i IN INDICES OF v_tab LOOP DBMS_OUTPUT.PUT_LINE('índice = ' || i); END LOOP; END; |
Saída:
1 2 3 4 5 6 |
Índices da coleção: índice = 1 índice = 2 índice = 3 índice = 5 |
3. PAIRS OF
O controle PAIRS OF fornece acesso tanto aos valores quanto aos índices de uma coleção, combinando as funcionalidades de VALUES OF e INDICES OF.
Exemplo:
1 2 3 4 5 6 7 8 9 10 11 |
DECLARE TYPE tab_type IS TABLE OF PLS_INTEGER INDEX BY PLS_INTEGER; v_tab tab_type; BEGIN v_tab(1) := 10; v_tab(2) := 20; v_tab(3) := 30; v_tab(5) := 50; DBMS_OUTPUT.PUT_LINE('Índices e valores da coleção:'); FOR i, v IN PAIRS OF v_tab LOOP DBMS_OUTPUT.PUT_LINE('índice = ' || i || ', valor = ' || v); END LOOP; END; |
Saída:
1 2 3 4 5 6 |
Índices e valores da coleção: índice = 1, valor = 10 índice = 2, valor = 20 índice = 3, valor = 30 índice = 5, valor = 50 |
Expressões Qualificadas
As expressões qualificadas, introduzidas no Oracle 18c e aprimoradas no 21c, oferecem uma maneira mais concisa de inicializar e manipular coleções.
Sintaxe Básica
1 |
typemark (qualified_expression) |
Tipos de Expressões Qualificadas
- Expressão qualificada vazia:
typemark()
- Expressão qualificada simples: Produz um único valor
- Expressão qualificada agregada: Produz uma lista de valores
Exemplo com Associative Array
1 2 3 4 5 6 7 8 9 10 11 12 13 |
DECLARE TYPE tab_type IS TABLE OF VARCHAR2(1) INDEX BY PLS_INTEGER; v_tab tab_type; BEGIN -- Expressão qualificada com Oracle 21c (associação posicional) v_tab := tab_type('A', 'B', 'C'); -- Exibindo resultados FOR i, v IN PAIRS OF v_tab LOOP DBMS_OUTPUT.PUT_LINE('índice = ' || i || ', valor = ' || v); END LOOP; END; |
Saída:
1 2 3 4 |
índice = 1, valor = A índice = 2, valor = B índice = 3, valor = C |
Expressões Qualificadas Agregadas com Associações de Iterador
Estas são expressões que permitem criar e preencher coleções de forma mais concisa e flexível, usando iteradores para definir os valores e, opcionalmente, os índices.
Associação de Iterador
1 2 3 4 5 6 7 8 9 10 |
DECLARE TYPE tab_type IS TABLE OF NUMBER INDEX BY PLS_INTEGER; v_tab tab_type; BEGIN v_tab := tab_type(FOR i IN 1..4 => i/2); FOR i, v IN PAIRS OF v_tab LOOP DBMS_OUTPUT.PUT_LINE('índice = ' || i || ', valor = ' || v); END LOOP; END; |
Saída:
1 2 3 4 |
índice = 1, valor = .5 índice = 2, valor = 1 índice = 3, valor = 1.5 índice = 4, valor = 2 |
Nesse exemplo:
1 |
v_tab := tab_type(FOR i IN 1..4 => i/2); |
- Criamos uma coleção com 4 elementos.
- O índice
i
vai de 1 a 4. - Cada elemento recebe o valor de
i/2
.
Esta é a forma mais simples de associação de iterador, onde os índices são implicitamente definidos pela sequência do loop.
Associação de Iterador de Índice
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
DECLARE TYPE tab_type IS TABLE OF NUMBER INDEX BY PLS_INTEGER; v_tab tab_type; v_tab_new tab_type; BEGIN v_tab := tab_type(FOR i IN 1..4 => i/2); v_tab_new := tab_type(FOR i, v IN PAIRS OF v_tab INDEX i+10 => v+10); DBMS_OUTPUT.PUT_LINE('v_tab_new:'); FOR i, v IN PAIRS OF v_tab_new LOOP DBMS_OUTPUT.PUT_LINE('índice = ' || i || ', valor = ' || v); END LOOP; END; |
Saída:
1 2 3 4 5 6 |
v_tab_new: índice = 11, valor = 10.5 índice = 12, valor = 11 índice = 13, valor = 11.5 índice = 14, valor = 12 |
Neste exemplo:
1 |
v_tab_new := tab_type(FOR i, v IN PAIRS OF v_tab INDEX i+10 => v+10); |
- Iteramos sobre os pares (índice, valor) de
v_tab
. - Para cada par, criamos um novo elemento em
v_tab_new
. - O novo índice é
i+10
(índice original + 10). - O novo valor é
v+10
(valor original + 10).
Resultado:
- O índice 1 de v_tab (valor 0.5) torna-se índice 11 em v_tab_new (valor 10.5)
- O índice 2 de v_tab (valor 1) torna-se índice 12 em v_tab_new (valor 11)
- E assim por diante…
A palavra-chave INDEX
permite definir explicitamente os novos índices.
Associação de Iterador de Sequência
1 2 3 4 5 6 7 8 9 10 11 |
DECLARE TYPE tab_type IS TABLE OF NUMBER INDEX BY PLS_INTEGER; v_tab tab_type; BEGIN v_tab := tab_type(FOR i IN 10..14 SEQUENCE => i/2); DBMS_OUTPUT.PUT_LINE('v_tab atualizado:'); FOR i, v IN PAIRS OF v_tab LOOP DBMS_OUTPUT.PUT_LINE('índice = ' || i || ', valor = ' || v); END LOOP; END; |
Saída:
1 2 3 4 5 6 7 |
v_tab atualizado: índice = 1, valor = 5 índice = 2, valor = 5.5 índice = 3, valor = 6 índice = 4, valor = 6.5 índice = 5, valor = 7 |
Neste exemplo:
1 |
v_tab := tab_type(FOR i IN 10..14 SEQUENCE => i/2); |
- Usamos
SEQUENCE
para criar uma sequência de 5 elementos (10 a 14). - Cada elemento recebe o valor de
i/2
. - Os índices são atribuídos sequencialmente começando de 1, independentemente dos valores de
i
.
Resultado:
- índice 1: 10/2 = 5
- índice 2: 11/2 = 5.5
- índice 3: 12/2 = 6
- índice 4: 13/2 = 6.5
- índice 5: 14/2 = 7
A palavra-chave SEQUENCE
é útil quando queremos usar um range de valores para cálculo, mas manter a indexação padrão da coleção.
Considerações sobre Nested Tables
Ao usar expressões qualificadas com Nested Tables, é necessário usar INDEX ou SEQUENCE para evitar erros. Por exemplo:
1 2 3 |
v_tab := tab_type(FOR i IN 1..4 INDEX i => i/2); -- Ou v_tab := tab_type(FOR i IN 1..4 SEQUENCE => i/2); |
Ambas as formas produzirão o mesmo resultado para Nested Tables, mas são necessárias para esclarecer como os elementos devem ser inseridos na coleção.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
DECLARE TYPE tab_type IS TABLE OF NUMBER; v_tab tab_type; BEGIN v_tab := tab_type(FOR i IN 1..4 INDEX i => i/2); -- Ou v_tab := tab_type(FOR i IN 1..4 SEQUENCE => i/2); FOR i, v IN PAIRS OF v_tab LOOP DBMS_OUTPUT.PUT_LINE('índice = ' || i || ', valor = ' || v); END LOOP; END; |
Conclusão
Os novos controles de iteração de coleções (VALUES OF, INDICES OF, PAIRS OF) e as expressões qualificadas aprimoradas no Oracle 21c oferecem maneiras mais eficientes e legíveis de trabalhar com coleções em PL/SQL. Eles permitem um código mais conciso e expressivo, facilitando a manutenção e compreensão de lógicas complexas envolvendo coleções.
Ao utilizar essas funcionalidades, considere:
- A escolha entre VALUES OF, INDICES OF e PAIRS OF depende das necessidades específicas de iteração.
- Expressões qualificadas podem simplificar a inicialização de coleções, mas é preciso estar atento às diferenças entre tipos de coleções.
- O uso de associações de iterador, índice e sequência oferece flexibilidade na manipulação de coleções, mas requer atenção à sintaxe correta para cada tipo de coleção.
Pratique usando esses recursos em diferentes cenários para se familiarizar com suas capacidades e limitações, sempre considerando a clareza e manutenibilidade do código resultante. Essas novas funcionalidades não apenas melhoram a eficiência do código, mas também aumentam significativamente sua legibilidade e manutenibilidade.