Oracle Paquete PL/SQL: tipo, especificación, cuerpo [Ejemplo]

⚡ Resumen inteligente

Los paquetes PL/SQL agrupan procedimientos, funciones, variables, cursores y excepciones relacionados en un único objeto de esquema con una especificación y un cuerpo. La especificación declara la interfaz pública, mientras que el cuerpo contiene la implementación privada, lo que mejora la modularidad y el rendimiento.

  • 📦 Definición del paquete: Un paquete es un grupo lógicoping de subprogramas y objetos relacionados, compilados y almacenados como un único objeto de base de datos.
  • 📋 Especificaciones del paquete: Declara las variables públicas, cursores, tipos, excepciones, procedimientos y funciones accesibles desde fuera del paquete.
  • 🧱 Cuerpo del paquete: Define todos los elementos declarados en la especificación, además de los elementos privados que solo se pueden invocar desde dentro del paquete.
  • 🔁 Sobrecarga: Varios subprogramas pueden compartir un mismo nombre cuando difieren en el número de parámetros, los tipos de parámetros o el tipo de retorno.
  • 🔗 Referencia y dependencia: Los elementos públicos se denominan como package_name.element_name, y el cuerpo sigue dependiendo de la especificación.
  • 🤖 Asistencia de IA: Asistentes de IA como GitHub Copilot elaboran especificaciones de paquetes, cuerpos y subprogramas sobrecargados a partir de un comentario.

Oracle Descripción general de la especificación y la estructura del paquete PL/SQL.

¿Qué es el paquete? Oracle?

Oracle PL / SQL El paquete es un grupo lógicoping de relacionados subprogramas (procedimiento/función) en un solo elemento. Un paquete se compila y se almacena como un objeto de base de datos que se puede reutilizar posteriormente.

Componentes de paquetes

Un paquete PL/SQL tiene dos componentes.

  • Especificación del paquete
  • Cuerpo del paquete

Especificación del paquete

La especificación del paquete consiste en una declaración de todos los elementos públicos. las variables, cursores, objetos, procedimientos, funciones y excepciones.

A continuación se detallan algunas características de la especificación del paquete.

  • Los elementos declarados en la especificación pueden ser accedidos desde fuera del paquete. Dichos elementos se conocen como elementos públicos.
  • La especificación del paquete es un elemento independiente, lo que significa que puede existir por sí sola sin un cuerpo de paquete.
  • Cada vez que se hace referencia a un paquete, se crea una instancia de dicho paquete para esa sesión en particular.
  • Una vez creada la instancia para una sesión, todos los elementos del paquete que se inician en esa instancia son válidos hasta el final de la sesión.

Sintaxis

CREATE [OR REPLACE] PACKAGE <package_name> 
IS
<sub_program and public element declaration>
.
.
END <package name>

La sintaxis anterior muestra la creación de la especificación del paquete.

Cuerpo del paquete

El cuerpo del paquete consta de la definición de todos los elementos presentes en la especificación del paquete. También puede contener definiciones de elementos que no están declarados en la especificación; estos elementos se denominan elementos privados y solo se pueden invocar desde dentro del paquete.

A continuación se detallan las características de la caja de un paquete.

  • Debe contener definiciones para todos los subprogramas/cursores que se hayan declarado en la especificación.
  • También puede contener más subprogramas u otros elementos que no estén declarados en la especificación. Estos se denominan elementos privados.
  • Es un objeto dependiente y depende de la especificación del paquete.
  • El estado del cuerpo del paquete pasa a ser "Inválido" cada vez que se compila la especificación. Por lo tanto, es necesario recompilarlo cada vez que se compile la especificación.
  • Los elementos privados deben definirse primero antes de usarse en el cuerpo del paquete.
  • La primera parte del cuerpo del paquete es la declaración global. Esta incluye variables, cursores y elementos privados (declaración anticipada) que son visibles para todo el paquete.
  • La última parte del paquete es la parte de inicialización del paquete, que se ejecuta una sola vez cada vez que se hace referencia a un paquete por primera vez en la sesión.

Sintaxis:

CREATE [OR REPLACE] PACKAGE BODY <package_name>
IS
<global_declaration part>
<Private element definition>
<sub_program and public element definition>
.
<Package Initialization> 
END <package_name>

La sintaxis anterior muestra la creación del cuerpo del paquete.

Ahora vamos a ver cómo hacer referencia a los elementos del paquete en el programa.

Elementos del paquete de referencia

Una vez que los elementos se declaran y definen en el paquete, necesitamos hacer referencia a ellos para poder utilizarlos.

Se puede hacer referencia a todos los elementos públicos del paquete llamando al nombre del paquete seguido del nombre del elemento separado por un punto, es decir ' . '.

Las variables públicas del paquete también se pueden usar de la misma manera para asignar y obtener valores de ellas, es decir, . '.

Crear paquete en PL/SQL

En PL/SQL, cada vez que se hace referencia a un paquete o se le llama en una sesión, se crea una nueva instancia para ese paquete.

Oracle proporciona una función para inicializar elementos del paquete o realizar cualquier actividad en el momento de la creación de esta instancia a través de la 'Inicialización del paquete'.

Esto no es más que un bloque de ejecución que se escribe en el cuerpo del paquete después de definir todos sus elementos. Este bloque se ejecutará cada vez que se haga referencia al paquete por primera vez en la sesión.

La siguiente captura de pantalla muestra cómo se coloca el bloque de inicialización del paquete dentro del cuerpo del paquete al crearlo.

Creación de un paquete PL/SQL con un bloque de inicialización de paquete en el cuerpo del paquete.

Sintaxis

CREATE [OR REPLACE] PACKAGE BODY <package_name>
IS
<Private element definition>
<sub_program and public element definition>
.
BEGIN
<Package Initialization> 
END <package_name>

La sintaxis anterior muestra la definición de inicialización del paquete en el cuerpo del paquete.

Declaraciones futuras

La declaración anticipada o referencia en el paquete no es más que declarar los elementos privados por separado y definirlos en la parte posterior del cuerpo del paquete.

Los elementos privados solo pueden ser referenciados si ya están declarados en el cuerpo del paquete. Por esta razón, se utiliza la declaración anticipada. Sin embargo, su uso es poco común, ya que en la mayoría de los casos los elementos privados se declaran y definen en la primera parte del cuerpo del paquete.

La declaración anticipada es una opción proporcionada por OracleNo es obligatorio, y su uso depende de las necesidades del programador.

La captura de pantalla que aparece a continuación muestra cómo se declara un elemento privado de forma anticipada y cómo se define posteriormente en el cuerpo del paquete.

Declaración anticipada de un elemento privado en un Oracle Cuerpo del paquete PL/SQL

Sintaxis:

CREATE [OR REPLACE] PACKAGE BODY <package_name>
IS
<Private element declaration>
.
.
.
<Public element definition that refer the above private element>
.
.
<Private element definition> 
.
BEGIN
<package_initialization code>; 
END <package_name>

La sintaxis anterior muestra una declaración adelantada. Los elementos privados se declaran por separado en la parte adelantada del paquete y se han definido en la parte posterior.

Uso de cursores en el paquete

A diferencia de otros elementos, hay que tener cuidado al usar cursores dentro del paquete.

Si el cursor está definido en la especificación del paquete o en la parte global del cuerpo del paquete, entonces, una vez abierto, el cursor permanecerá hasta el final de la sesión.

Por lo tanto, siempre se debe usar el atributo de cursor '%ISOPEN' para verificar el estado del cursor antes de hacer referencia a él.

La sobrecarga

La sobrecarga consiste en tener varios subprogramas con el mismo nombre. Estos subprogramas se diferencian entre sí por el número de parámetros, el tipo de parámetros o el tipo de retorno. En otras palabras, se considera sobrecarga a los subprogramas con el mismo nombre pero con diferente número de parámetros, diferente tipo de parámetros o diferente tipo de retorno.

Esto resulta útil cuando varios subprogramas necesitan realizar la misma tarea, pero la forma de llamarlos debe ser diferente para cada uno. En este caso, el nombre del subprograma se mantiene igual para todos y los parámetros se modifican según la instrucción de llamada.

Ejemplo 1: En este ejemplo, crearemos un paquete para obtener y establecer los valores de la información de un empleado en la tabla 'emp'. La función get_record devolverá el registro de salida para el número de empleado dado, y el procedimiento set_record insertará el registro de salida en la tabla emp.

Paso 1) Creación de la especificación del paquete

La captura de pantalla a continuación muestra la especificación del paquete guru99_get_set que se está creando en Oracle.

Creación de la especificación del paquete guru99_get_set con set_record y get_record en Oracle

CREATE OR REPLACE PACKAGE guru99_get_set
IS
PROCEDURE set_record (p_emp_rec IN emp%ROWTYPE);
FUNCTION get_record (p_emp_no IN NUMBER) RETURN emp%ROWTYPE;
END guru99_get_set;
/

Salida:

Package created

Code Explicación

  • Code líneas 1-5: Se creó la especificación del paquete guru99_get_set con un procedimiento y una función. Estos dos elementos son ahora públicos en este paquete.

Paso 2) El paquete contiene un cuerpo donde se definen todos los procedimientos y funciones. En este paso, se crea el cuerpo del paquete.

La captura de pantalla a continuación muestra la definición del cuerpo del paquete guru99_get_set en Oracle.

Definir el cuerpo del paquete guru99_get_set con set_record, get_record y el bloque de inicialización.

CREATE OR REPLACE PACKAGE BODY guru99_get_set
IS
PROCEDURE set_record(p_emp_rec IN emp%ROWTYPE)
IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO emp
VALUES(p_emp_rec.emp_name,p_emp_rec.emp_no, p_emp_rec.salary,p_emp_rec.manager);
COMMIT;
END set_record;
FUNCTION get_record(p_emp_no IN NUMBER)
RETURN emp%ROWTYPE
IS
l_emp_rec emp%ROWTYPE;
BEGIN
SELECT * INTO l_emp_rec FROM emp where emp_no=p_emp_no;
RETURN l_emp_rec;
END get_record;
BEGIN
dbms_output.put_line('Control is now executing the package initialization part');
END guru99_get_set;
/

Salida:

Package body created

Code Explicación

  • Code línea 7: Creando el cuerpo del paquete.
  • Code líneas 9-16: Definir el elemento 'set_record' que se declara en la especificación. Esto es equivalente a definir un procedimiento independiente en PL/SQL.
  • Code líneas 17-24: Definir el elemento 'get_record'. Es lo mismo que definir una función independiente.
  • Code líneas 25-26: Definiendo la parte de inicialización del paquete.

Paso 3) Se crea un bloque anónimo para insertar y mostrar los registros haciendo referencia al paquete creado anteriormente.

La captura de pantalla a continuación muestra el bloque anónimo que llama al paquete, junto con su salida en Oracle.

Bloque anónimo que llama a guru99_get_set para insertar y mostrar un registro de empleado con salida

DECLARE
l_emp_rec emp%ROWTYPE;
l_get_rec emp%ROWTYPE;
BEGIN
dbms_output.put_line('Insert new record for employee 1004');
l_emp_rec.emp_no:=1004;
l_emp_rec.emp_name:='CCC';
l_emp_rec.salary:=20000;
l_emp_rec.manager:='BBB';
guru99_get_set.set_record(l_emp_rec);
dbms_output.put_line('Record inserted');
dbms_output.put_line('Calling get function to display the inserted record');
l_get_rec:=guru99_get_set.get_record(1004);
dbms_output.put_line('Employee name: '||l_get_rec.emp_name);
dbms_output.put_line('Employee number:'||l_get_rec.emp_no);
dbms_output.put_line('Employee salary:'||l_get_rec.salary);
dbms_output.put_line('Employee manager:'||l_get_rec.manager);
END;
/

Salida:

Insert new record for employee 1004
Control is now executing the package initialization part
Record inserted
Calling get function to display the inserted record
Employee name: CCC
Employee number: 1004
Employee salary: 20000
Employee manager: BBB

Code Explicación:

  • Code líneas 34-37: Rellenar los datos para la variable de tipo registro en un bloque anónimo para llamar al elemento 'set_record' del paquete.
  • Code línea 38: Se ha realizado una llamada al método 'set_record' del paquete guru99_get_set. El paquete se ha instanciado y permanecerá activo hasta el final de la sesión. La inicialización del paquete se ejecuta al ser la primera llamada, y el elemento 'set_record' inserta el registro en la tabla.
  • Code línea 41: Se llama al elemento 'get_record' para mostrar los detalles del empleado insertado. El paquete se menciona por segunda vez durante esta llamada, pero la parte de inicialización no se ejecuta de nuevo, ya que el paquete ya está inicializado en esta sesión.
  • Code líneas 42-45: Impresión de los detalles del empleado.

Dependencia en paquetes

Dado que el paquete es un grupo lógicoping Entre las cosas relacionadas, existen algunas dependencias. A continuación se detallan las dependencias que deben tenerse en cuenta.

  • Una especificación es un objeto independiente.
  • El cuerpo del paquete depende de las especificaciones.
  • El cuerpo del paquete se puede compilar por separado. Cada vez que se compila la especificación, es necesario volver a compilar el cuerpo, ya que de lo contrario dejará de ser válido.
  • El subprograma dentro del cuerpo del paquete que depende de un elemento privado debe definirse únicamente después de la declaración del elemento privado.
  • Los objetos de la base de datos a los que se hace referencia en la especificación y en el cuerpo del documento deben estar en un estado válido en el momento de la compilación del paquete.

Información del paquete

Una vez creado el paquete, la información del paquete, como el origen del paquete, los detalles del subprograma y los detalles de sobrecarga, están disponibles en el Oracle tablas del diccionario de datos.

La siguiente tabla muestra la tabla del diccionario de datos y la información del paquete disponible en cada tabla.

Nombre de la tabla Mareas Ideales para Lecciones Consulta
TODOS LOS OBJETOS Proporciona detalles del paquete como object_id, creation_date, last_ddl_time, etc. Contiene los objetos creados por todos los usuarios. SELECCIONAR * DE todos_objetos donde nombre_objeto =''
OBJETOS DE USUARIO Proporciona detalles del paquete como object_id, creation_date, last_ddl_time, etc. Contiene los objetos creados por el usuario actual. SELECCIONAR * DE objetos_usuario donde nombre_objeto =''
TODO_FUENTE Proporciona el origen de los objetos creados por todos los usuarios. SELECCIONAR * DE all_source donde nombre = ''
FUENTE_USUARIO Proporciona el origen de los objetos creados por el usuario actual. SELECCIONAR * DE fuente_usuario donde nombre = ''
TODOS_PROCEDIMIENTOS Proporciona detalles del subprograma, como object_id, detalles de sobrecarga, etc., creados por todos los usuarios. SELECCIONAR * DE todos los procedimientos Donde nombre_objeto=' '
USUARIO_PROCEDIMIENTOS Proporciona detalles del subprograma como object_id, detalles de sobrecarga, etc. creado por el usuario actual. SELECCIONAR * DE user_procedures WHERE object_name=' '

UTL_FILE – Descripción general

UTL_FILE es un paquete de utilidades independiente proporcionado por Oracle Para realizar tareas especiales, se utiliza principalmente para leer y escribir archivos del sistema operativo desde paquetes o subprogramas PL/SQL. Dispone de funciones independientes para introducir y extraer información de los archivos. Además, permite leer y escribir en el conjunto de caracteres nativo.

El programador puede usar esto para escribir archivos del sistema operativo de cualquier tipo, y el archivo se escribirá directamente en el servidor de la base de datos. El nombre y la ruta del directorio se especifican al momento de escribir.

Preguntas Frecuentes

Los paquetes proporcionan modularidad, ocultación de información y un diseño de aplicaciones más sencillo. La especificación expone una interfaz pública, mientras que el cuerpo oculta la implementación. Oracle En la primera llamada, carga un paquete en la memoria, de modo que las llamadas posteriores a subprogramas evitan la entrada/salida de disco y se ejecutan más rápido.

Un paquete agrupa muchos elementos relacionados. subprogramas y objetos compartidos bajo un mismo nombre, separando una especificación pública de un cuerpo privado. Un procedimiento o función independiente es un único objeto de esquema independiente sin esa división entre interfaz e implementación.

Sí, si la especificación declara únicamente variables, constantes, tipos o excepciones. El cuerpo se vuelve obligatorio una vez que la especificación declara cualquier procedimiento, función o cursor, ya que debe proporcionar su implementación. De lo contrario, la especificación puede ser independiente.

Utilice DROP PACKAGE para eliminar tanto la especificación como el cuerpo, o DROP PACKAGE BODY para eliminar solo el cuerpo. Recompile un paquete no válido con ALTER PACKAGE package_name COMPILE, o COMPILE BODY para reconstruir solo el cuerpo después de los cambios.

El atributo %ROWTYPE declara un grabar cuyos campos coinciden con las columnas de la tabla emp. El uso de emp%ROWTYPE mantiene los parámetros get_record y set_record alineados con la estructura de la tabla, por lo que los cambios de columna requieren menos modificaciones de código.

Sí. Cada sesión que hace referencia a un paquete obtiene su propia instancia y estado del paquete, que persiste durante la vida de esa sesión. Recompilar el cuerpo descarta el estado y genera el error ORA-04068 en la siguiente llamada.

Sí. Copiloto de GitHub Borradores de especificaciones de paquetes, cuerpos coincidentes y subprogramas sobrecargados a partir de un comentario, y sugiere parámetros %ROWTYPE. RevRevise los límites generados, el bloque de inicialización y el manejo de excepciones antes de la implementación.

Los asistentes de IA analizan un paquete en busca de estados no válidos, definiciones de cuerpo faltantes y cadenas de dependencia que se rompen cuando cambia la especificación. Esta revisión mediante aprendizaje automático detecta subprogramas sobrecargados ambiguos y riesgos de recompilación antes de que el paquete llegue a producción.

Resumir este post con: