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 est possible de configurer correctement de tels paramètres uniquement lorsque fiMeta est inclus dans TFDStoredProc.FetchOptions.Items et 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 d'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 (y compris les résultats implicites (EN) Oracle 12c) 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 puis utilisez NextRecordSet pour passer aux curseurs suivants. Une fois sur le curseur suivant, le précédent n'est plus accessible. Pour plus d'informations, voir 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, avant les appels Open suivants, vous devrez appeler la méthode Disconnect. 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.

Alors 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.

ROWID implicites

Oracle prend en charge l'extraction implicite des ROWID (EN). Lors d'une requête SELECT FOR UPDATE, Oracle inclut implicitement la pseudo-colonne ROWID dans les résultats.

Un ensemble de données FireDAC représente un champ ROWID implicite sous la forme d'une colonne masquée. Le champ ROWID implicite n'est pas disponible dans la propriété Fields, mais il peut être lu depuis la propriété Table.

Si vous voulez extraire explicitement la pseudo-colonne ROWID afin qu'elle soit incluse dans la propriété Fields, vous devez inclure ROWID dans votre liste de champ SELECT (SELECT <autres champs>, ROWID FROM ).

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.

Facultativement, définissez la propriété ResourceOptions.ServerOutputSize 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;

Administration d'une instance de base de données Oracle

Vous pouvez utiliser le composant service TFDOracleAdmin pour administrer une instance de base de données Oracle.

TFDOracleAdmin.Startup et TFDOracleAdmin.Shutdown vous permettent de démarrer ou d'arrêter une instance de base de données Oracle ou d'ouvrir ou de fermer une base de données PDB (pluggable database).

Voir aussi