Oracle PL/SQL BULK COLLECT: Exemplo FORALL

โšก Resumo Inteligente

COLETA EM GRANDE QUANTIDADE em Oracle PL/SQL busca vรกrias linhas de uma sรณ vez em uma coleรงรฃo, enquanto FORALL envia operaรงรตes DML em massa de volta para o banco de dados. Ambos reduzem as trocas de contexto entre os mecanismos SQL e PL/SQL, aumentando o desempenho.

  • ๐Ÿ“ฆ COLETA EM GRANDE QUANTIDADE: Busca vรกrias linhas em uma รบnica passagem para uma variรกvel de coleรงรฃo, substituindo a busca lenta linha por linha.
  • ๐Ÿ” PARA TODOS: Executa uma รบnica operaรงรฃo INSERT, UPDATE ou DELETE em toda a coleรงรฃo com uma รบnica troca de contexto.
  • ๐Ÿ“ Clรกusula LIMIT: Limita a quantidade de linhas que cada comando BULK COLLECT carrega, protegendo a memรณria da sessรฃo em tabelas grandes.
  • ๐Ÿ“Š Atributos de COLETA EM MASSA: O atributo %BULK_ROWCOUNT(n) informa quantas linhas a n-รฉsima instruรงรฃo DML FORALL afetou.
  • โš™๏ธ Coleรงรตes necessรกrias: A clรกusula INTO deve ter como alvo um tipo de coleรงรฃo, como uma tabela aninhada ou uma matriz associativa.
  • ๐Ÿค– Assistรชncia de IA: Assistentes de IA como o GitHub Copilot elaboram blocos BULK COLLECT e FORALL e sinalizam a ausรชncia de uma clรกusula LIMIT.

Oracle Visรฃo geral das funรงรตes PL/SQL BULK COLLECT e FORALL com clรกusula LIMIT

O que รฉ COLETA EM GRANEL?

A COLETA EM MASSA reduz as trocas de contexto entre os SQL e o mecanismo PL/SQL, permitindo que o mecanismo SQL busque os registros de uma sรณ vez.

Oracle PL/SQL Oferece a funcionalidade de buscar registros em lote, em vez de buscรก-los um por um. Este comando BULK COLLECT pode ser usado em uma instruรงรฃo SELECT para preencher os registros em lote ou para buscar um conjunto de registros. cursor Em lote. Como o BULK COLLECT busca os registros em lote, a clรกusula INTO deve sempre conter uma variรกvel de tipo de coleรงรฃo. A principal vantagem de usar o BULK COLLECT รฉ o aumento de desempenho, que reduz a interaรงรฃo entre o banco de dados e o mecanismo PL/SQL.

Sintaxe:

SELECT <column1> BULK COLLECT INTO bulk_variable FROM <table name>;
FETCH <cursor_name> BULK COLLECT INTO <bulk_variable>;

Na sintaxe acima, BULK COLLECT รฉ usado para coletar os dados das instruรงรตes SELECT e FETCH.

Clรกusula FORALL

A instruรงรฃo FORALL executa Operaรงรตes DML em dados em massa. Assemelha-se a uma instruรงรฃo de laรงo FOR, exceto que em um laรงo FOR as aรงรตes ocorrem no nรญvel do registro, enquanto em FORALL nรฃo existe o conceito de laรงo. Em vez disso, todos os dados presentes no intervalo especificado sรฃo processados โ€‹โ€‹simultaneamente.

Sintaxe:

FORALL <loop_variable> in <lower range> .. <higher range>

<DML operations>;

Na sintaxe acima, a operaรงรฃo DML fornecida serรก executada para todos os dados presentes entre os limites inferior e superior.

Clรกusula LIMIT

O conceito de coleta em massa carrega todos os dados na variรกvel de coleรงรฃo de destino de uma sรณ vez, ou seja, todos os dados serรฃo inseridos na variรกvel de coleรงรฃo de uma sรณ vez. No entanto, isso nรฃo รฉ recomendรกvel quando o nรบmero total de registros a serem carregados รฉ muito grande, pois, ao tentar carregar todos os dados, o PL/SQL consome mais memรณria da sessรฃo. Portanto, รฉ sempre bom limitar o tamanho dessa operaรงรฃo de coleta em massa.

Esse limite de tamanho pode ser facilmente alcanรงado introduzindo a condiรงรฃo ROWNUM na instruรงรฃo SELECT, enquanto que no caso de um cursor isso nรฃo รฉ possรญvel.

Para superar isso, Oracle forneceu a clรกusula LIMIT que define o nรบmero de registros que precisam ser incluรญdos no lote.

Sintaxe:

FETCH <cursor_name> BULK COLLECT INTO <bulk_variable> LIMIT <size>;

Na sintaxe acima, a instruรงรฃo de busca do cursor usa a instruรงรฃo BULK COLLECT juntamente com a clรกusula LIMIT.

BULK COLLECT Atributos

Semelhante aos atributos de cursor, o comando BULK COLLECT possui a funรงรฃo %BULK_ROWCOUNT(n), que retorna o nรบmero de linhas afetadas na n-รฉsima instruรงรฃo DML do comando FORALL, ou seja, fornece a contagem de registros afetados na instruรงรฃo FORALL para cada valor da variรกvel de coleรงรฃo. O termo 'n' indica a sequรชncia do valor na coleรงรฃo para a qual a contagem de linhas รฉ necessรกria.

1 exemplo: Neste exemplo, vamos projetar todos os nomes dos funcionรกrios da tabela `emp` usando BULK COLLECT e tambรฉm vamos aumentar o salรกrio de todos os funcionรกrios em 5000 usando FORALL.

A captura de tela abaixo mostra este exemplo de BULK COLLECT e FORALL juntamente com sua saรญda em Oracle.

Exemplo de COLETA EM MASSA com LIMIT e FORALL atualizando o salรกrio do funcionรกrio em Oracle PL/SQL

DECLARE
CURSOR guru99_det IS SELECT emp_name FROM emp;
TYPE lv_emp_name_tbl IS TABLE OF VARCHAR2(50);
lv_emp_name lv_emp_name_tbl;
BEGIN
OPEN guru99_det;
FETCH guru99_det BULK COLLECT INTO lv_emp_name LIMIT 5000;
FOR c_emp_name IN lv_emp_name.FIRST .. lv_emp_name.LAST
LOOP
Dbms_output.put_line('Employee Fetched:'||c_emp_name);
END LOOP;
FORALL i IN lv_emp_name.FIRST .. lv_emp_name.LAST
UPDATE emp SET salary=salary+5000 WHERE emp_name=lv_emp_name(i);
COMMIT;
Dbms_output.put_line('Salary Updated');
CLOSE guru99_det;
END;
/

saรญda

Employee Fetched:BBB
Employee Fetched:XXX
Employee Fetched:YYY
Salary Updated

Code Explicaรงรฃo:

  • Code linha 2: Declarando o cursor guru99_det para a instruรงรฃo 'SELECT emp_name FROM emp'.
  • Code linha 3: Declarando lv_emp_name_tbl como um tipo de tabela VARCHAR2(50).
  • Code linha 4: Declarando lv_emp_name como o tipo lv_emp_name_tbl.
  • Code linha 6: Abrindo o cursor.
  • Code linha 7: Obtendo o cursor usando BULK COLLECT com o tamanho LIMIT definido como 5000 e armazenando-o na variรกvel lv_emp_name.
  • Code linhas 8-11: Configure um loop FOR para imprimir todos os registros da coleรงรฃo lv_emp_name.
  • Code linha 12: Utilizando a funรงรฃo FORALL para atualizar o salรกrio de todos os funcionรกrios em 5000.
  • Code linha 14: Comprometer-se com o transaรงรฃo.

Perguntas Frequentes

Nรฃo. Um comando BULK COLLECT SELECT nunca gera NO_DATA_FOUND; em vez disso, retorna uma coleรงรฃo vazia. Sempre teste a coleรงรฃo com o mรฉtodo .COUNT antes de usar o comando loo.pingCaso contrรกrio, vocรช poderรก processar zero linhas silenciosamente.

SAVE EXCEPTIONS permite que FORALL continue sendo executado mesmo quando linhas individuais falham. As linhas com falha sรฃo armazenadas em SQL%BULK_EXCEPTIONS, entรฃo Oracle gera o erro ORA-24381, que vocรช captura em um exceรงรฃo manipulador para inspecionar cada erro.

Use BULK COLLECT sempre que um loop ler muitas linhas. cursor O loop FOR busca uma linha por vez, portanto, a busca em lote combinada com FORALL pode ser executada muitas vezes mais rรกpido em grandes conjuntos de resultados.

BULK COLLECT retorna vรกrias linhas de uma sรณ vez, portanto, precisa de um contรชiner com vรกrias linhas. O destino INTO deve ser um coleรงรฃo como uma tabela aninhada, VARRAY ou matriz associativa, e nรฃo uma รบnica variรกvel escalar.

Nรฃo. Um cabeรงalho FORALL executa exatamente uma instruรงรฃo INSERT, UPDATE, DELETE ou MERGE. Somente os valores em suas clรกusulas VALUES e WHERE podem mudar a cada iteraรงรฃo. Para vรกrias instruรงรตes, use instruรงรตes FORALL separadas.

O processamento em lote pode ser de vรกrias a mais de cem vezes mais rรกpido do que o cรณdigo linha por linha, porque BULK COLLECT e FORALL condensam milhares de trocas de contexto do mecanismo em poucas, reduzindo drasticamente a sobrecarga em grandes volumes de dados.

Sim. Travas deslizantes portรกteis Copiloto do GitHub O script descreve rascunhos de coletas BULK COLLECT, loops DML FORALL e clรกusulas LIMIT a partir de um comentรกrio, e sugere declaraรงรตes de tipo de coleรงรฃo, embora vocรช deva revisar os tamanhos dos lotes e o tratamento de erros por conta prรณpria.

Assistentes de IA analisam loops que buscam ou alteram uma linha por vez e recomendam reescrevรช-los com BULK COLLECT, LIMIT e FORALL. Essa anรกlise por aprendizado de mรกquina detecta limitaรงรตes LIMIT ausentes e gargalos de desempenho antes da produรงรฃo.

Resuma esta postagem com: