Oracle Package PL/SQL : type, spécification, corps [Exemple]

⚡ Résumé intelligent

Les packages PL/SQL regroupent les procédures, fonctions, variables, curseurs et exceptions associés au sein d'un même objet de schéma, doté d'une spécification et d'un corps. La spécification définit l'interface publique, tandis que le corps contient l'implémentation privée, ce qui améliore la modularité et les performances.

  • 📦 Définition du paquet : Un paquet est un groupe logiqueping de sous-programmes et d'objets associés, compilés et stockés sous forme d'un seul objet de base de données.
  • 📋 Spécifications du package: Déclare les variables publiques, les curseurs, les types, les exceptions, les procédures et les fonctions accessibles depuis l'extérieur du package.
  • 🧱 Corps du colis : Définit chaque élément déclaré dans la spécification, ainsi que les éléments privés qui ne peuvent être appelés que depuis l'intérieur du package.
  • (I.e. Surcharge: Plusieurs sous-programmes peuvent partager un même nom lorsque leur nombre de paramètres, leurs types de paramètres ou leur type de retour diffèrent.
  • 🔗 Référence et dépendance : Les éléments publics sont appelés sous la forme nom_du_package.nom_de_l'élément, et le corps reste dépendant de la spécification.
  • 🤖 Assistance IA : Les assistants IA tels que GitHub Copilot peuvent générer des spécifications de paquets, des corps et des sous-programmes surchargés à partir d'un commentaire.

Oracle Aperçu des spécifications et de la structure du package PL/SQL

Qu'est-ce que le paquet dans Oracle?

Oracle PL / SQL Le paquet est un groupe logiqueping de apparentés sous-programmes (procédure/fonction) en un seul élément. Un package est compilé et stocké sous forme d'objet de base de données pouvant être réutilisé ultérieurement.

Composants des packages

Un package PL/SQL comporte deux composants.

  • Spécifications du paquet
  • Corps du paquet

Spécifications du paquet

La spécification du paquet consiste en une déclaration de tous les publics les variables, curseurs, objets, procédures, fonctions et exceptions.

Vous trouverez ci-dessous quelques caractéristiques des spécifications de l'emballage.

  • Les éléments déclarés dans la spécification sont accessibles depuis l'extérieur du paquet. Ces éléments sont appelés éléments publics.
  • La spécification du paquet est un élément autonome, ce qui signifie qu'elle peut exister seule, sans corps de paquet.
  • Chaque fois qu'un paquet est référencé, une instance de ce paquet est créée pour cette session particulière.
  • Une fois l'instance créée pour une session, tous les éléments du package initiés dans cette instance sont valides jusqu'à la fin de la session.

Syntaxe

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

La syntaxe ci-dessus illustre la création de la spécification du paquet.

Corps du paquet

Le corps du paquetage contient la définition de tous les éléments présents dans la spécification du paquetage. Il peut également contenir des définitions d'éléments non déclarés dans la spécification ; ces éléments sont dits privés et ne peuvent être appelés que depuis l'intérieur du paquetage.

Vous trouverez ci-dessous les caractéristiques d'un emballage.

  • Il doit contenir les définitions de tous les sous-programmes/curseurs déclarés dans la spécification.
  • Il peut également contenir d'autres sous-programmes ou éléments non déclarés dans la spécification. On les appelle éléments privés.
  • Il s'agit d'un objet dépendant, et il dépend de la spécification du paquet.
  • L'état du corps du paquet devient « Invalide » à chaque compilation de la spécification. Il est donc nécessaire de le recompiler après chaque compilation de la spécification.
  • Les éléments privés doivent d’abord être définis avant d’être utilisés dans le corps du package.
  • La première partie du corps du package est la partie de déclaration globale. Celle-ci comprend les variables, les curseurs et les éléments privés (déclaration anticipée) visibles par l'ensemble du package.
  • La dernière partie du paquet est la partie d'initialisation du paquet, qui s'exécute une seule fois chaque fois qu'un paquet est référencé pour la première fois dans la session.

syntaxe:

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 syntaxe ci-dessus illustre la création du corps du paquet.

Nous allons maintenant voir comment faire référence aux éléments du package dans le programme.

Éléments de package référents

Une fois les éléments déclarés et définis dans le package, nous devons faire référence à ces éléments pour les utiliser.

Tous les éléments publics du paquet peuvent être référencés en appelant le nom du paquet suivi du nom de l'élément, séparés par un point, c'est-à-dire « . '.

Les variables publiques du package peuvent également être utilisées de la même manière pour leur assigner et récupérer des valeurs, c'est-à-dire « . '.

Créer un package en PL/SQL

En PL/SQL, chaque fois qu'un package est référencé ou appelé dans une session, une nouvelle instance est créée pour ce package.

Oracle fournit une fonctionnalité permettant d'initialiser les éléments du package ou d'effectuer toute activité au moment de la création de cette instance via « Initialisation du package ».

Il s'agit simplement d'un bloc d'exécution inséré dans le corps du package après la définition de tous ses éléments. Ce bloc sera exécuté lors de la première utilisation du package dans la session.

La capture d'écran ci-dessous montre comment le bloc d'initialisation du package est placé à l'intérieur du corps du package lors de la création d'un package.

Création d'un package PL/SQL avec un bloc d'initialisation de package dans le corps du package

Syntaxe

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

La syntaxe ci-dessus montre la définition de l'initialisation du package dans le corps du package.

Déclarations à terme

La déclaration anticipée ou la référence dans le package consiste simplement à déclarer les éléments privés séparément et à les définir dans la partie ultérieure du corps du package.

On ne peut faire référence aux éléments privés que s'ils sont préalablement déclarés dans le corps du paquet. C'est pourquoi on utilise la déclaration anticipée. Cependant, son usage est plutôt inhabituel, car la plupart du temps, les éléments privés sont déclarés et définis dans la première partie du corps du paquet.

La déclaration anticipée est une option proposée par OracleSon utilisation n'est pas obligatoire et dépend des besoins du programmeur.

La capture d'écran ci-dessous montre comment un élément privé est déclaré à l'avance puis défini ultérieurement dans le corps du package.

Déclaration anticipée d'un élément privé dans un Oracle Corps du package PL/SQL

syntaxe:

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 syntaxe ci-dessus montre une déclaration directe. Les éléments privés sont déclarés séparément dans la partie avant du package, et ils ont été définis dans la partie ultérieure.

Utilisation des curseurs dans le package

Contrairement aux autres éléments, il faut être prudent lorsqu'on utilise des curseurs à l'intérieur du package.

Si le curseur est défini dans la spécification du paquet ou dans la partie globale du corps du paquet, alors le curseur, une fois ouvert, persistera jusqu'à la fin de la session.

Il convient donc toujours d'utiliser l'attribut de curseur '%ISOPEN' pour vérifier l'état du curseur avant de s'y référer.

Surcharge

La surcharge consiste à avoir plusieurs sous-programmes portant le même nom. Ces sous-programmes diffèrent par le nombre ou le type de leurs paramètres, ou par leur type de retour. Autrement dit, des sous-programmes ayant le même nom mais un nombre ou un type de paramètres différent, ou un type de retour différent, constituent une surcharge.

Ceci est utile lorsque plusieurs sous-programmes doivent effectuer la même tâche, mais que leur mode d'appel diffère. Dans ce cas, le nom du sous-programme reste identique pour tous, et les paramètres sont modifiés selon l'instruction d'appel.

Exemple 1: Dans cet exemple, nous allons créer un package permettant de lire et de modifier les informations d'un employé dans la table « emp ». La fonction `get_record` renverra le type d'enregistrement correspondant au numéro d'employé donné, et la procédure `set_record` insérera cet enregistrement dans la table « emp ».

Étape 1) Création des spécifications de l'emballage

La capture d'écran ci-dessous montre la création de la spécification du package guru99_get_set dans Oracle.

Création de la spécification du package guru99_get_set avec set_record et get_record dans 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;
/

Sortie :

Package created

Code Explication

  • Code lignes 1-5 : Création de la spécification du package guru99_get_set avec une procédure et une fonction. Ces deux éléments sont désormais publics dans ce package.

Étape 2) Le package contient un corps de package, où sont définies concrètement toutes les procédures et fonctions. Cette étape consiste à créer le corps du package.

La capture d'écran ci-dessous montre la définition du corps du package guru99_get_set dans Oracle.

Définition du corps du package guru99_get_set avec set_record, get_record et le bloc d'initialisation

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

Sortie :

Package body created

Code Explication

  • Code ligne 7: Création du corps du paquet.
  • Code lignes 9-16 : Définition de l'élément « set_record » déclaré dans la spécification. Cela revient à définir une procédure autonome en PL/SQL.
  • Code lignes 17-24 : Définition de l'élément 'get_record'. Cela revient à définir une fonction autonome.
  • Code lignes 25-26 : Définition de la partie initialisation du package.

Étape 3) Création d'un bloc anonyme pour insérer et afficher les enregistrements en faisant référence au package créé ci-dessus.

La capture d'écran ci-dessous montre le bloc anonyme qui appelle le paquet, ainsi que sa sortie dans Oracle.

Bloc anonyme appelant guru99_get_set pour insérer et afficher un enregistrement d'employé avec sortie

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

Sortie :

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 Explication:

  • Code lignes 34-37 : Remplissage des données de la variable de type enregistrement dans un bloc anonyme pour appeler l'élément 'set_record' du package.
  • Code ligne 38: Un appel a été effectué à la méthode `set_record` du package `guru99_get_set`. Le package est maintenant instancié et restera actif jusqu'à la fin de la session. L'initialisation du package est exécutée puisqu'il s'agit du premier appel à ce package, et l'enregistrement est inséré dans la table par l'élément `set_record`.
  • Code ligne 41: L'élément « get_record » est appelé pour afficher les détails de l'employé inséré. Le package est référencé une seconde fois lors de cet appel, mais la partie initialisation n'est pas réexécutée, car le package est déjà initialisé dans cette session.
  • Code lignes 42-45 : Impression des détails de l'employé.

Dépendance dans les packages

Étant donné que le paquet est un groupe logiqueping Parmi les éléments connexes, il existe certaines dépendances. Voici les dépendances à prendre en compte.

  • Une spécification est un objet autonome.
  • Le boîtier de l'emballage dépend des spécifications.
  • Le corps du paquet peut être compilé séparément. À chaque compilation de la spécification, le corps doit être recompilé, car il devient invalide.
  • Le sous-programme du corps du package qui dépend d'un élément privé ne doit être défini qu'après la déclaration de l'élément privé.
  • Les objets de base de données mentionnés dans la spécification et le corps du document doivent être dans un état valide au moment de la compilation du package.

Informations sur le forfait

Une fois le package créé, les informations le concernant, telles que le code source, les détails des sous-programmes et les détails des surcharges, sont disponibles dans le Oracle Tables du dictionnaire de données.

Le tableau ci-dessous présente le tableau du dictionnaire de données et les informations sur les packages disponibles dans chaque tableau.

Nom de la table Description Question
TOUS_OBJETS Fournit les détails du package tels que object_id, creation_date, last_ddl_time, etc. Il contient les objets créés par tous les utilisateurs. SELECT * FROM all_objects où object_name =' '
OBJETS_UTILISATEUR Fournit les détails du package tels que object_id, creation_date, last_ddl_time, etc. Il contient les objets créés par l'utilisateur actuel. SELECT * FROM user_objects où object_name =' '
ALL_SOURCE Donne la source des objets créés par tous les utilisateurs. SELECT * FROM all_source où nom=' '
USER_SOURCE Donne la source des objets créés par l'utilisateur actuel. SELECT * FROM user_source où nom=' '
ALL_PROCEDURES Fournit les détails du sous-programme, tels que l'identifiant de l'objet, les détails de la surcharge, etc., créés par tous les utilisateurs. SELECT * FROM all_procedures WHERE object_name=' '
USER_PROCEDURES Donne les détails du sous-programme comme object_id, les détails de surcharge, etc. créés par l'utilisateur actuel. SELECT * FROM user_procedures WHERE object_name=' '

UTL_FILE – Aperçu

UTL_FILE est un paquet utilitaire distinct fourni par Oracle Il permet d'effectuer des tâches spécifiques. Il est principalement utilisé pour lire et écrire des fichiers système depuis des packages ou sous-programmes PL/SQL. Il dispose de fonctions distinctes pour insérer et extraire des informations de fichiers. Il permet également la lecture et l'écriture dans le jeu de caractères natif.

Le programmeur peut utiliser cette fonction pour écrire des fichiers système de tout type, qui seront directement enregistrés sur le serveur de base de données. Le nom et le chemin d'accès au répertoire sont indiqués au moment de l'écriture.

FAQ

Les paquets offrent modularité, masquage des informations et une conception d'applications simplifiée. La spécification expose une interface publique tandis que le corps du paquet masque l'implémentation. Oracle charge un package en mémoire lors du premier appel, de sorte que les appels de sous-programmes ultérieurs évitent les E/S disque et s'exécutent plus rapidement.

Un paquet regroupe de nombreux éléments connexes sous-programmes et des objets partagés sous un même nom, séparant ainsi une spécification publique d'un corps privé. Une procédure ou une fonction autonome est un objet de schéma unique et indépendant, sans cette séparation entre interface et implémentation.

Oui, si la spécification ne déclare que des variables, des constantes, des types ou des exceptions. Un corps devient obligatoire dès lors que la spécification déclare une procédure, une fonction ou un curseur, car le corps doit en fournir l'implémentation. Autrement, la spécification peut être autonome.

Utilisez DROP PACKAGE pour supprimer à la fois la spécification et le corps du paquet, ou DROP PACKAGE BODY pour supprimer uniquement le corps. Recompilez un paquet invalide avec ALTER PACKAGE nom_du_paquet COMPILE, ou COMPILE BODY pour reconstruire uniquement le corps après modifications.

L'attribut %ROWTYPE déclare un record dont les champs correspondent aux colonnes de la table emp. L'utilisation de emp%ROWTYPE permet de conserver l'alignement des paramètres get_record et set_record avec la structure de la table, ce qui réduit le nombre de modifications de code nécessaires lors de la modification des colonnes.

Oui. Chaque session qui référence un paquetage obtient sa propre instanciation et son propre état de paquetage, qui persistent pendant toute la durée de la session. La recompilation du corps de la requête supprime cet état et provoque l'erreur ORA-04068 lors du prochain appel.

Oui. Copilote GitHub rédige les spécifications des paquets, les corps correspondants et les sous-programmes surchargés à partir d'un commentaire, et suggère les paramètres %ROWTYPE. RevVeuillez consulter les limites générées, le bloc d'initialisation et la gestion des exceptions avant le déploiement.

Des assistants d'IA analysent un package à la recherche d'états invalides, de définitions de corps manquantes et de chaînes de dépendances rompues lors de modifications de la spécification. Cette analyse par apprentissage automatique signale les sous-programmes surchargés ambigus et les risques de recompilation avant la mise en production du package.

Résumez cet article avec :