Verwenden von Oracle mit FireDAC

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu Arbeiten mit DBMS (FireDAC)


Erweiterte Datentypen von Oracle

PL/SQL-Tabellen

FireDAC unterstützt Oracle PL/SQL-Tabellen als Parameter von anonymen PL/SQL-Blöcken, gespeicherten Prozeduren und Funktionen. Beachten Sie, dass sich eine PL/SQL zugeordnete Tabelle von VARRAY und Sammlungen unterscheidet. FireDAC unterstützt die beiden letzteren nicht.

Geben Sie TFDParam.ArrayType = atPLSQLTable an, um einen Parameter als PL/SQL-Tabelle festzulegen. Setzen Sie ArraySize auf die maximale Tabellengröße, bevor Sie ExecProc aufrufen. Wenn der INOUT- und OUT-Parameter ArraySize kleiner als die Anzahl der auf der Serverseite zugewiesenen Tabellenelemente ist, dann wird eine Exception ausgelöst.

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

Mit den Eigenschaften TFDParam.AsXxxs[<Index>] können Sie Parameterwerte lesen und schreiben. Der Index ist nullbasiert; auf der Serverseite ist der Index dagegen 1-basiert. Die leeren Elemente haben einen NULL-Wert und können mit TFDParam.IsNulls[<Index>] getestet werden.

Beispiel des serverseitigen Skripts:

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

Beispiel des clientseitigen Codes zur Zuweisung von Memozeilen zum Tabellenparameter, Ausführen von Prozeduren, Lesen von Tabelleneinträgen und Füllen des Memos:

 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]);

Siehe auch die Demo "FireDAC\Samples\DBMS Specific\Oracle\PLSQLAssocArray".

PL/SQL-Datensätze

FireDAC unterstützt Oracle PL/SQL-Datensätze als Parameter von gespeicherten Prozeduren und Funktionen. PL/SQL-Datensätze unterscheiden sich von Objekten. FireDAC unterstützt Oracle-Objekte nicht.

Solche Parameter können nur korrekt konfiguriert werden, wenn fiMeta in TFDStoredProc.FetchOptions.Items enthalten und ParamBindMode = pbByName ist. FireDAC erweitert dann den Datensatz in eine lineare Liste mit zugehörigen Params-Einträgen, wobei jeder Eintrag einen Namen <Parametername>$<Datensatzfeldname> hat.

Beispiel des serverseitigen Skripts:

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

Beispiel des clientseitigen Codes zur Zuweisung von Parameterwerten:

 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;

Siehe auch die Demo "FireDAC\Samples\DBMS Specific\Oracle\PLSQLRecs".

Erweiterte Cursors von Oracle

Arbeiten mit REF CURSOR von Oracle

FireDAC unterstützt REF CURSOR von Oracle, der von anonymen Oracle PL/SQL-Blöcken, gespeicherten Prozeduren und Funktionen zurückgegeben wird. Rufen Sie die Methode Open zum Öffnen des ersten Cursors auf, und wechseln Sie mit der Methode NextRecordSet zu den folgenden Cursors. Nach dem Wechseln zum nächsten Cursor kann auf den vorherigen nicht mehr zugegriffen werden. Im Kapitel Anweisungsstapel finden Sie weitere Einzelheiten.

Zum Beispiel:

 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;

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

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

Hinweis: Wenn der REF CURSOR mit dynamischem SQL-Anweisungstext geöffnet wird, dann sollten Sie vor nachfolgenden Open-Aufrufen die Methode Disconnect aufrufen. Und zwar, weil FireDAC die Datenmenge vorbereitet hat und dieselbe Cursorstruktur wie beim ersten Open-Aufruf erwartet.

Zum Beispiel:

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

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

Arbeiten mit verschachtelten Oracle-Cursors

FireDAC unterstützt CURSOR-Typspalten in SELECT-Listen. In der Liste können sich mehrere CURSORs befinden. Aber ein in einen anderen CURSOR verschachtelter CURSOR wird nicht unterstützt. FireDAC setzt solche Spalten auf dtRowSetRef und erstellt dafür ein TDataSetField. Um diese Rowsets zu verarbeiten, muss die Anwendung TFDMemTable verwenden und deren Eigenschaft DataSetField auf eine TDataSetField-Referenz setzen.

Beim Navigieren der Anwendung durch die Hauptdatenmenge werden die verschachtelten Datenmengen automatisch geöffnet und aktualisiert, um die Datensätze des verschachtelten Cursors für einen aktuellen Datensatz der Hauptdatenmenge bereitzustellen.

Beispiele dazu finden Sie in der Demo "FireDAC\Samples\DBMS Specific\Oracle\NestedCursors".

Aktualisieren von Cursor-Daten

Zum Aktualisieren von REF CURSOR oder Datensätzen von verschachtelten Cursors muss die Anwendung die Hauptabfrage erneut ausführen.

Für die Bearbeitung von REF CURSOR oder Datensätzen von verschachtelten Cursors muss die Anwendung Eintragsaktualisierungen überschreiben.

Implizite ROWIDs

Oracle unterstützt implizites Abrufen von ROWIDs. Wenn Sie eine SELECT FOR UPDATE-Abfrage durchführen, fügt Oracle implizit die ROWID-Pseudospalte den Ergebnissen hinzu.

Ein FireDAC-Datensatz repräsentiert ein implizites ROWID-Feld als versteckte Spalte. Das implizite ROWID-Feld ist nicht in der Eigenschaft Felder verfügbar, Sie können es jedoch von der Eigenschaft Tabelle lesen.

Wenn Sie die ROWID-Pseudospalte explizit abrufen möchten, damit sie in der Eigenschaft Felder enthalten ist, müssen Sie ROWID in Ihre SELECT-Feldliste (SELECT <other fields>, ROWID FROM ) hinzufügen.

Bereitstellen von Server-Rückmeldungen

Backend-Anwendungen von Oracle können Rückmeldungen an eine Frontend-Anwendung mit dem DBMS_OUTPUT (EN)-Paket senden. FireDAC lässt das automatische Empfangen des DBMS_OUTPUT-Inhalts zu.

Legen Sie optional für ResourceOptions.ServerOutputSize die maximale Puffergröße fest. Setzen Sie ResourceOptions.ServerOutput auf True, um DBMS_OUTPUT zu aktivieren. Nach der Ausführung einer SQL-Anweisung kann die Anwendung die DBMS_OUTPUT-Rückmeldungen mit Messages verarbeiten. Die Verarbeitung von DBMS_OUTPUT wirkt sich auf die Leistung aus, daher muss diese normalerweise deaktiviert sein.

Zum Beispiel:

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;

Verwalten einer Oracle-Datenbank-Instanz

Sie können die TFDOracleAdmin-Dienstkomponente verwenden, um eine Oracle-Datenbank-Instanz zu verwalten.

Mit TFDOracleAdmin.Startup und TFDOracleAdmin.Shutdown können Sie eine Oracle-Instanz-Datenbank beginnen oder beenden, oder eine "pluggable" Datenbank (PDB) öffnen oder schließen.

Siehe auch