Utilisation d'Oracle avec FireDAC

De RAD Studio
Aller à : navigation, rechercher

Remonter à Utilisation des SGBD (FireDAC)


Types de données avancées Oracle

Tables PL/SQL

FireDAC supporte les tables PL/SQL Oracle en tant que paramètres des blocs anonymes PL/SQL, des procédures stockées et des fonctions. Notez qu'une table PL/SQL associée est différente des tableaux variables (VARRAY) et des collections. FireDAC ne supporte pas ces derniers.

Pour définir un paramètre en tant que table PL/SQL, spécifiez TFDParam.ArrayType = atPLSQLTable. Définissez ArraySize sur une taille de table maximale avant l'appel à ExecProc. Lorsque la valeur ArraySize du paramètre INOUT et OUT sera inférieure au nombre d'éléments de table assignés côté serveur, une exception sera déclenchée.

 [FireDAC][Phys][Ora] ORA-06513: PL/SQL: index for PL/SQL table out of range for host language array
 ORA-06512: at line 2

Pour lire ou écrire des valeurs de paramètres, utilisez les propriétés TFDParam.AsXxxs[<index>]. L'index est basé sur zéro, alors que côté serveur, il est basé sur 1. Les éléments vides ont une valeur NULL et peuvent être testés en utilisant TFDParam.IsNulls[<index>].

Voici un exemple de script côté serveur :

 CREATE OR REPLACE PACKAGE FDQA_TestPack AS
   TYPE TVC2Tbl IS TABLE OF VARCHAR2(50) INDEX BY BINARY_INTEGER;
   PROCEDURE TestPLSQLArray(ATable in out TVC2Tbl);
 END ADQA_testpack;
 /
 
 CREATE OR REPLACE PACKAGE BODY FDQA_TestPack AS
   PROCEDURE TestPLSQLArray(ATable IN OUT TVC2Tbl) IS
   BEGIN
     for i in ATable.First .. ATable.Last loop
       ATable(i) := '*' || ATable(i) || '*';
     end loop;
   END;
 END FDQA_testpack;
 /

Et voici un exemple de code côté client qui assigne des lignes mémo au paramètre table, exécute les procédures, lit les éléments de la table et renseigne le mémo :

 var
   i: Integer;
 
 FDStoredProc1.PackageName := 'FDQA_TESTPACK';
 FDStoredProc1.StoredProcName := 'TESTPLSQLARRAY';
 FDStoredProc1.Prepare;
 
 FDStoredProc1.Params[0].ArraySize := Memo1.Lines.Count;
 for i := 0 to Memo1.Lines.Count - 1 do
   FDStoredProc1.Params[0].AsStrings[i] := Memo1.Lines[i];
 Memo1.Lines.Clear;
 
 FDStoredProc1.ExecProc;
 for i := 0 to FDStoredProc1.Params[0].ArraySize - 1 do
   Memo1.Lines.Add(FDStoredProc1.Params[0].AsStrings[i]);

Voir également la démo FireDAC\Samples\DBMS Specific\Oracle\PLSQLAssocArray.

Enregistrements PL/SQL

FireDAC supporte les enregistrements PL/SQL Oracle en tant que paramètres des procédures stockées et des fonctions. Notez qu'un enregistrement PL/SQL est différent des objets. FireDAC ne supporte pas les objets Oracle.

Il n'est possible de configurer correctement de tels paramètres que lorsque fiMeta est inclus dans TFDStoredProc.FetchOptions.Items et que ParamBindMode = pbByName. FireDAC développe alors l'enregistrement dans une liste plate d'éléments Params correspondants, où chaque élément a un nom <nom du paramètre>$<nom du champ de l'enregistrement>.

Voici un exemple de script côté serveur :

 CREATE OR REPLACE PACKAGE ClientPack IS
   TYPE t_clnt_data IS RECORD (
        client_id numeric,
        name varchar2(10),
        act boolean
   );
   PROCEDURE ClntProc(ARec IN t_clnt_data);
 END ClientPack;
 /

Et voici un exemple de code côté client qui assigne les valeurs de paramètres :

 FDStoredProc1.PackageName := 'MYPACK';
 FDStoredProc1.StoredProcName := 'CLNTPROC';
 FDStoredProc1.Prepare;
 FDStoredProc1.ParamByName('AREC$CLIENT_ID').Value := 100;
 FDStoredProc1.ParamByName('AREC$NAME').Value := 'Client 1';
 FDStoredProc1.ParamByName('AREC$ACT').Value := True;
 FDStoredProc1.ExecProc;

Voir également la démo FireDAC\Samples\DBMS Specific\Oracle\PLSQLRecs.

Curseurs avancés Oracle

Utilisation du curseur REF CURSOR Oracle

FireDAC supporte le curseur REF CURSOR Oracle, renvoyé par les blocs anonymes PL/SQL, les procédures stockées et les fonctions Oracle. Pour ouvrir le premier curseur, appelez la méthode Open, et pour passer aux curseurs suivants, utilisez la méthode NextRecordSet. Une fois passé au curseur suivant, le précédent n'est plus accessible. Pour plus de détails, voir la rubrique Groupes de commandes.

Par exemple :

 CREATE PROCEDURE TestRefCrs (ACrs1 IN OUT SYS_REFCURSOR, ACrs2 IN OUT SYS_REFCURSOR) AS
 BEGIN
   OPEN ACrs1 FOR SELECT * FROM "Orders";
   OPEN ACrs2 FOR SELECT * FROM "Order Details";
 END;

Utilisation de TFDStoredProc :

 FDStoredProc1.FetchOptions.AutoClose := False;
 FDStoredProc1.StoredProcName := 'TESTREFCRS';
 FDStoredProc1.Open;
 // work with "Orders" table data
 FDStoredProc1.NextRecordSet;
 // work with "Order Details" table data
 FDStoredProc1.Close;

Utilisation de TFDQuery :

 FDQuery1.FetchOptions.AutoClose := False;
 FDQuery1.Open('BEGIN TestRefCrs(:p1, :p2); END;');
 // work with "Orders" table data
 FDQuery1.NextRecordSet;
 // work with "Order Details" table data
 FDQuery1.Close;

Remarque : Si le curseur REF CURSOR est ouvert en utilisant un texte de commande SQL dynamique, vous devez appeler la méthode Disconnect avant les prochains appels à Open. En effet, FireDAC conserve la préparation de l'ensemble de données et attend la même structure de curseur que lors du premier appel à Open.

Par exemple :

 CREATE PROCEDURE TestDynCrs (ASQL IN VARCHAR2, ACrs OUT SYS_REFCURSOR) AS
 BEGIN
   OPEN ACrs FOR ASQL;
 END;

Utilisation de TFDQuery :

 FDQuery1.FetchOptions.AutoClose := False;
 FDQuery1.SQL.Text := 'BEGIN TestDynCrs(:p1, :p2); END;';
 
 FDQuery1.Params[0].AsString := 'SELECT * FROM "Orders"';
 FDQuery1.Open;
 // work with "Orders" table data
 FDQuery1.Close;
 
 FDQuery1.Params[0].AsString := 'SELECT * FROM "Order Details"';
 FDQuery1.Disconnect;
 FDQuery1.Open;
 // work with "Order Details" table data
 FDQuery1.Close;

Utilisation des curseurs imbriqués Oracle

FireDAC supporte les colonnes de type CURSOR dans les listes SELECT. Il peut y avoir plusieurs curseurs de type CURSOR dans la liste. Mais FireDAC ne supporte pas la présence d'un curseur imbriqué CURSOR dans un curseur de type CURSOR. FireDAC définit de telles colonnes sur dtRowSetRef et crée pour elles un TDataSetField. Pour traiter leurs ensembles de lignes, l'application doit utiliser TFDMemTable, et définir sa propriété DataSetField sur une référence TDataSetField.

Tandis que l'application navigue à travers l'ensemble de données principal, les ensembles de données imbriqués sont automatiquement ouverts et actualisés pour fournir les enregistrements du curseur imbriqué d'un enregistrement en cours dans l'ensemble de données principal.

Pour obtenir des exemples, voir la démo FireDAC\Samples\DBMS Specific\Oracle\NestedCursors.

Mise à jour des données des curseurs

Pour actualiser les enregistrements d'un curseur REF CURSOR ou d'un curseur imbriqué, l'application doit à nouveau exécuter la requête principale.

Pour modifier les enregistrements d'un curseur REF CURSOR ou d'un curseur imbriqué, l'application doit redéfinir la validation des mises à jour.

Retour d'informations sur le serveur

Les applications backend Oracle peuvent envoyer des informations à une application frontale en utilisant le package DBMS_OUTPUT. FireDAC permet la réception automatique du contenu de DBMS_OUTPUT.

Vous avez la possibilité de définir la propriété ResourceOptions.ServerOutputSize de TFDConnection sur la taille de tampon maximale. Pour activer DBMS_OUTPUT, définissez ResourceOptions.ServerOutput sur True. Après l'exécution d'une commande SQL, il se peut que l'application traite les informations de DBMS_OUTPUT en utilisant Messages. Notez que le traitement de DBMS_OUTPUT affecte les performances. Il doit donc normalement être désactivé.

Par exemple :

 var
   i: Integer;
 ...
 FDConnection1.ResourceOptions.ServerOutput := True;
 with FDQuery1.SQL do begin
   Clear;
   Add('begin');
   Add('  dbms_output.put_line(''Hello World !'');');
   Add('end;');
 end;
 FDQuery1.ExecSQL;
 if FDConnection1.Messages <> nil then begin
   Memo1.Lines.Clear;
   for i := 0 to FDConnection1.Messages.ErrorCount - 1 do
     Memo1.Lines.Add(FDConnection1.Messages[i].Message);
 end;

Voir aussi