Oracle PL/SQL BULK COLLECT: Ejemplo FORALL

โšก Resumen inteligente

RECOGIDA A GRANEL en Oracle PL/SQL recupera varias filas a la vez y las almacena en una colecciรณn, mientras que FORALL envรญa grandes cantidades de operaciones DML a la base de datos. Ambas opciones reducen los cambios de contexto entre los motores SQL y PL/SQL, lo que mejora el rendimiento.

  • ๐Ÿ“ฆ RECOGIDA AL POR MAYOR: Recupera varias filas en una sola pasada y las almacena en una variable de colecciรณn, reemplazando la lenta recuperaciรณn fila por fila.
  • ๐Ÿ” PARA TODOS: Ejecuta una operaciรณn INSERT, UPDATE o DELETE en toda una colecciรณn con un รบnico cambio de contexto.
  • ๐Ÿ“ Clรกusula LIMIT: Limita la cantidad de filas que carga cada operaciรณn BULK COLLECT, protegiendo asรญ la memoria de sesiรณn en tablas grandes.
  • ๐Ÿ“Š Atributos de COLECCIร“N MASIVA: El atributo %BULK_ROWCOUNT(n) informa cuรกntas filas afectรณ la enรฉsima instrucciรณn DML FORALL.
  • โš™๏ธ Colecciones requeridas: La clรกusula INTO debe apuntar a un tipo de colecciรณn, como una tabla anidada o una matriz asociativa.
  • ๐Ÿค– Asistencia de IA: Los asistentes de IA, como GitHub Copilot, elaboran bloques BULK COLLECT y FORALL e indican la falta de una clรกusula LIMIT.

Oracle Descripciรณn general de PL/SQL BULK COLLECT y FORALL con clรกusula LIMIT

ยฟQuรฉ es la RECOGER A GRANEL?

BULK COLLECT reduce los cambios de contexto entre el SQL y el motor PL/SQL y permite que el motor SQL obtenga los registros de una sola vez.

Oracle PL / SQL Proporciona la funcionalidad de recuperar los registros en masa en lugar de recuperarlos uno por uno. Este BULK COLLECT se puede utilizar en una instrucciรณn SELECT para llenar los registros en masa o para recuperar un cursor En lote. Dado que BULK COLLECT recupera los registros en lote, la clรกusula INTO siempre debe contener una variable de tipo colecciรณn. La principal ventaja de usar BULK COLLECT es que mejora el rendimiento al reducir la interacciรณn entre la base de datos y el motor PL/SQL.

Sintaxis:

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

En la sintaxis anterior, BULK COLLECT se utiliza para recopilar los datos de las sentencias SELECT y FETCH.

Clรกusula FORALL

La instrucciรณn FORALL realiza Operaciones DML sobre datos masivos. Se asemeja a un bucle FOR, con la diferencia de que en un bucle FOR las acciones se realizan a nivel de registro, mientras que en FORALL no existe el concepto de bucle. En cambio, todos los datos presentes en el rango especificado se procesan simultรกneamente.

Sintaxis:

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

<DML operations>;

En la sintaxis anterior, la operaciรณn DML especificada se ejecutarรก para todos los datos que se encuentren entre el rango inferior y el superior.

Clรกusula LรMITE

El concepto de recopilaciรณn masiva carga todos los datos en la variable de recopilaciรณn de destino de una sola vez. Sin embargo, esto no es recomendable cuando el nรบmero total de registros que se deben cargar es muy grande, ya que al intentar cargar todos los datos mediante PL/SQL se consume mucha memoria de sesiรณn. Por lo tanto, siempre es conveniente limitar el tamaรฑo de esta operaciรณn de recopilaciรณn masiva.

Este lรญmite de tamaรฑo se puede lograr fรกcilmente introduciendo la condiciรณn ROWNUM en la instrucciรณn SELECT, mientras que en el caso de un cursor esto no es posible.

Para superar esto, Oracle ha proporcionado la clรกusula LIMIT que define el nรบmero de registros que deben incluirse en el lote.

Sintaxis:

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

En la sintaxis anterior, la instrucciรณn de obtenciรณn de cursor utiliza la instrucciรณn BULK COLLECT junto con la clรกusula LIMIT.

Atributos de RECOGER A GRANEL

De forma similar a los atributos del cursor, BULK COLLECT tiene %BULK_ROWCOUNT(n) que devuelve el nรบmero de filas afectadas en la enรฉsima instrucciรณn DML de la instrucciรณn FORALL; es decir, proporciona el recuento de registros afectados en la instrucciรณn FORALL para cada valor de la variable de colecciรณn. El tรฉrmino 'n' indica la secuencia del valor en la colecciรณn para el cual se necesita el recuento de filas.

Ejemplo 1: En este ejemplo, proyectaremos todos los nombres de los empleados de la tabla emp usando BULK COLLECT, y tambiรฉn vamos a aumentar el salario de todos los empleados en 5000 usando FORALL.

La captura de pantalla a continuaciรณn muestra este ejemplo de BULK COLLECT y FORALL junto con su salida en Oracle.

Ejemplo de BULK COLLECT con LIMIT y FORALL actualizando el salario del empleado en 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;
/

Resultado

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

Code Explicaciรณn:

  • Code lรญnea 2: Declarando el cursor guru99_det para la instrucciรณn 'SELECT emp_name FROM emp'.
  • Code lรญnea 3: Declarando lv_emp_name_tbl como una tabla de tipo VARCHAR2(50).
  • Code lรญnea 4: Declarar lv_emp_name como el tipo lv_emp_name_tbl.
  • Code lรญnea 6: Abriendo el cursor.
  • Code lรญnea 7: Obteniendo el cursor usando BULK COLLECT con un tamaรฑo LIMIT de 5000 en la variable lv_emp_name.
  • Code lรญneas 8-11: Configurar un bucle FOR para imprimir todos los registros de la colecciรณn lv_emp_name.
  • Code lรญnea 12: Utilizar FORALL para actualizar el salario de todos los empleados en 5000.
  • Code lรญnea 14: Cometer el transaccional.

Preguntas Frecuentes

No. Una consulta BULK COLLECT SELECT nunca genera NO_DATA_FOUND; en su lugar, devuelve una colecciรณn vacรญa. Siempre pruebe la colecciรณn con el mรฉtodo .COUNT antes de consultarla.pingDe lo contrario, podrรญa procesar cero filas silenciosamente.

SAVE EXCEPTIONS permite que FORALL siga ejecutรกndose cuando fallan filas individuales. Las filas que fallan se almacenan en SQL%BULK_EXCEPTIONS, luego Oracle genera ORA-24381, que se captura en un excepciรณn controlador para inspeccionar cada error.

Utilice BULK COLLECT siempre que un bucle lea muchas filas. cursor El bucle FOR recupera una fila por cada cambio, por lo que la recuperaciรณn masiva junto con FORALL puede ejecutarse mucho mรกs rรกpido en conjuntos de resultados grandes.

BULK COLLECT devuelve muchas filas a la vez, por lo que necesita un contenedor de varias filas. El destino INTO debe ser un recopilaciรณn como una tabla anidada, VARRAY o matriz asociativa, no una sola variable escalar.

No. Un encabezado FORALL controla una รบnica instrucciรณn INSERT, UPDATE, DELETE o MERGE. Solo los valores de sus clรกusulas VALUES y WHERE pueden cambiar en cada iteraciรณn. Para varias instrucciones, utilice instrucciones FORALL independientes.

El procesamiento por lotes puede ser varias veces, o incluso mรกs de cien veces, mรกs rรกpido que el cรณdigo fila por fila, porque BULK COLLECT y FORALL reducen miles de cambios de contexto del motor a unos pocos, lo que disminuye drรกsticamente la sobrecarga en grandes volรบmenes de datos.

Sรญ. Copiloto de GitHub Borradores de consultas BULK COLLECT, bucles DML FORALL y clรกusulas LIMIT a partir de un comentario, y sugiere declaraciones de tipos de colecciรณn, aunque usted mismo debe revisar los tamaรฑos de lote y el manejo de errores.

Los asistentes de IA analizan los bucles que recuperan o modifican una fila a la vez y recomiendan reescribirlos con BULK COLLECT, LIMIT y FORALL. Este anรกlisis mediante aprendizaje automรกtico detecta la falta de lรญmites LIMIT y los cuellos de botella de rendimiento antes de la producciรณn.

Resumir este post con: