Ausführen von SQL-Skripten (FireDAC)

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu Arbeiten mit Anweisungen (FireDAC)

Themen

Thema Beschreibung
Anweisungen zur Steuerung von SQL-Skripten TFDScript und das Hilfsprogramm FDExecutor unterstützen eine erweiterte Liste mit Anweisungen zur Steuerung von SQL-Skripten.
Entwickeln benutzerdefinierter Anweisungen TFDScript ermöglicht die Erweiterung des Anweisungssatzes zur Ausführungssteuerung von SQL-Skripten.

Allgemeine Informationen

Ein SQL-Skript ist eine Menge von SQL-, Ausführungssteuerungs- und Protokollierungsanweisungen. SQL-Skripte sind für Backend-Wartungsaufgaben, wie Backend-Erstellung von SQL-Objekten, Entfernen, Aktualisieren, erstes Laden von Daten usw., hilfreich.

Viele DBMSs ermöglichen mit Einschränkungen die Ausführung von mehreren SQL-Anweisungen in einem TFDQuery.ExecSQL-Aufruf als Stapel. Unterschiede zwischen einem SQL-Skript und einem SQL-Anweisungsstapel:

  • Das Skript ermöglicht die Verwendung aller möglicher SQL-Anweisungen in einem einzelnen Skript. Der Stapel kann je nach DBMS Beschränkungen unterliegen. Ein anonymer Oracle PL/SQL-Block darf beispielsweise keine DDL-Anweisung enthalten.
  • Das Skript kann in mehrere Transaktionen unterteilt werden. Der Stapel muss in einer Transaktion ausgeführt werden.
  • Das Skript ermöglicht die Verwendung von Nicht-SQL- und benutzerdefinierten Anweisungen. Der Stapel enthält nur Anweisungen, die von einem DBMS verstanden werden.
  • Das Skript kann in mehrere Unterskripte aufgeteilt werden. Der Stapel kann gespeicherte Prozeduren als getrennte Codeblöcke aufrufen.
  • Die Skriptausführung wird vollständig vom Client gesteuert. Die Stapelausführung wird nur vom DBMS gesteuert.
  • Im Gegensatz zur Stapelausführung kann die Skriptausführung protokolliert werden.
  • Im Gegensatz zur Stapelausführung stellt das Skript eine Rückmeldung über den Ausführungsfortschritt bereit.

TFDScript hat gegenüber Standardhilfsprogrammen viele Vorteile, wie z. B. die Möglichkeit, vollständig in die FireDAC-Anwendung integriert zu werden und die Anweisungen um benutzerdefinierte Skriptanweisungen zu erweitern. Die TFDScript-Komponente kann mit mehreren Standard-SQL-Skriptsyntaxen, wie der folgenden, arbeiten:

  • Oracle SQL*Plus
  • Microsoft ISQL/OSQL
  • MySQL mysql.exe/mysqldump.exe
  • Firebird/InterBase ISQL

Beispielsweise erstellt das folgende Firebird-Skript eine Datenbank, und es kann mit TFDScript ausgeführt werden:

 SET SQL DIALECT 3;
 SET NAMES UTF8;
 SET CLIENTLIB 'C:\fb25\bin\fbclient.dll';
 CREATE DATABASE 'E:\Test2.ib'
   USER 'sysdba' PASSWORD 'masterkey'
   PAGE_SIZE 16384
   DEFAULT CHARACTER SET NONE;
 
 SET TERM ^ ;
 
 CREATE PROCEDURE MY_PROC RETURNS (aParam INTEGER) AS
 BEGIN
   aParam = 10;
 END^

Ausführen des Skripts

Mit TFDScript kann ein Skript aus einer Datei ausgeführt werden, die durch SQLScriptFileName angegeben ist. Wenn SQLScriptFileName nicht angegeben ist, können Sie es aus einem Skript mit Null-Index aus der SQLScripts-Sammlung ausführen.

Hinweis: Sie können eine Datei mit einem SQL-Skript auch mit dem Hilfsprogramm FDExecutor ausführen.

Verwenden Sie beispielsweise zum Ausführen einer Skriptdatei das folgende Codefragment:

 with FDScript1 do begin
   SQLScriptFileName := 'c:\create.sql';
   ValidateAll;
   ExecuteAll;
 end;

Verwenden Sie den folgenden Code, um ein Skript im Arbeitsspeicher auszuführen:

 with FDScript1 do begin
   SQLScripts.Clear;
   SQLScripts.Add;
   with SQLScripts[0].SQL do begin
     Add('INSERT INTO Brands VALUES (1, ''Audi'')');
     Add('INSERT INTO Brands VALUES (2, ''BMW'')');
   end;
   ValidateAll;
   ExecuteAll;
 end;

Es gibt darüber hinaus noch einige andere Methoden, die die SQL-Skriptausführung vereinfachen. Sie können viele weitere Aspekte der Skriptausführung wie in Delphi-Code mit ScriptOptions und entsprechenden Skriptsteuerungsanweisungen steuern.

Das Skript kann auch andere Skripte, wie z. B. eine Unterroutine, mithilfe der Anweisungen @ <Skript>, @@ <Skript>, START <Skript> oder INPUT <Skript> aufrufen. In diesem Fall ist <Skript> entweder ein Elementname aus der SQLScripts-Sammlung oder ein externer Dateiname. Im folgenden Beispiel führt das "root"-Skript die Unterskripte "first" und "second" aus:

 with FDScript1.SQLScripts do begin
   Clear;
   with Add do begin
     Name := 'root';
     SQL.Add('@first');  // explicitly call 'first' script
     SQL.Add('@second'); // explicitly call 'second' script
   end;
   with Add do begin
     Name := 'first';
     SQL.Add('create table t1 (...);');
     SQL.Add('create table t2 (...);');
   end;
   with Add do begin
     Name := 'second';
     SQL.Add('create procedure p1 (...);');
     SQL.Add('create procedure p2 (...);');
   end;
 end;
 FDScript1.ValidateAll;
 FDScript1.ExecuteAll;

Ein SQL-Skript kann vollständig mit Unterskripten mithilfe der Methode ExecuteAll sowie schrittweise mit der Methode ExecuteStep ausgeführt werden. Letztere Methode eignet sich für GUI-Anwendungen, weil sie die Ausführung von Ad-hoc-Abfragen ermöglicht. Die nächste Anweisung wird extrahiert und ab der in Position angegebenen Position im Skript ausgeführt. Mit der Methode AbortJob können Sie die Ausführung des Skripts abbrechen.

Trennen von Anweisungen

Jede SQL-Anweisungen muss mit einem Anweisungstrennzeichen abgeschlossen werden. Der Vorgabewert für das Trennzeichen ist ";" und für MS SQL Server "GO". Eine Steuerungsanweisung muss nicht mit einem Anweisungstrennzeichen abgeschlossen werden. Das Trennzeichen kann wie in Delphi-Code mit der Option CommandSeparator oder wie in einem SQL-Skript mit den Anweisungen SET CMDSEP <Trennz> oder DELIMiter <Trennz> geändert werden. Verwenden Sie für SQL Server folgenden Code:

 INSERT INTO Brands VALUES (1, 'Audi')
 GO
 INSERT INTO Brands VALUES (2, 'BMW')
 GO

Verwenden Sie für Oracle:

 INSERT INTO Brands VALUES (1, 'Audi');
 INSERT INTO Brands VALUES (2, 'BMW');

Ein benutzerdefiniertes Trennzeichen verwenden Sie folgendermaßen:

 SET CMDSEP #
 INSERT INTO Brands VALUES (1, 'Audi')#
 INSERT INTO Brands VALUES (2, 'BMW')#

Wenn ein Skript Anweisungen oder Blöcke einer DB-Programmiersprache enthält, muss Folgendes beachtet werden:

DBMS SQL-Anweisungen Beschreibung
Firebird
  • CREATE FUNCTION
  • EXECUTE BLOCK <Codeblock>
Muss mit einem "/" abgeschlossen werden, oder ein anderes Trennzeichen als ";" muss festgelegt werden.
Oracle
  • CREATE PROCEDURE / FUNCTION / PACKAGE / usw.
  • BEGIN <Codeblock> END
Muss mit einem "/" abgeschlossen werden, oder ein anderes Trennzeichen als ";" muss festgelegt werden.
PostgreSQL
  • CREATE FUNCTION
  • DO <Codeblock>
Keine Aktion erforderlich.

Verwenden Sie für Firebird folgenden Code:

 SET CMDSEP #;
 EXECUTE BLOCK ... #
 SET CMDSEP ;#
 INSERT INTO Brands VALUES (3, 'Mercedes');

Andernfalls könnte die Anwendung einen Fehler wie den folgenden auslösen:

 [FireDAC][IB] Unexpected end of command line 3

Verwenden von Parametern

Ein SQL-Skript kann Folgendes referenzieren:

  • Parameter aus der TFDScript.Params-Sammlung. Verwenden Sie die Anweisung <code>VARiable <Name><Typ>=<Wert></code>, um einen Parameter in einem Skript festzulegen. Fügen Sie TFDScript.Params einen Parameter vor der Skriptausführung hinzu, um den Parameter im Code festzulegen.
  • Makros aus der TFDScript.Macros-Sammlung. Verwenden Sie die Anweisung <code>DEFine <Name>Typ<=><Wert>/code<, um ein Makro in einem Skript festzulegen. Fügen Sie TFDScript.Macros ein Makro vor der Skriptausführung hinzu, um das Makro im Code festzulegen. Setzen Sie MacroExpand auf True (Vorgabe), oder führen Sie SET DEFINE ON oder SET SCAN ON aus, um die Makroverarbeitung zu aktivieren.
  • Argumente mit der Syntax &<Argumentnummer>. Die Argumente können in der Eigenschaft TFDScript.Arguments als Argumente für die Methoden TFDScript.ExecuteFile oder ExecuteScript oder als Teil der Anweisungen @ / @@ angegeben werden.

Verwenden Sie zum Beispiel den folgenden Code, um Parameter festzulegen und zu verwenden:

 with FDScript1.SQLScripts[0].SQL do begin
   Add('VARIABLE name CHAR IN = ''aaa''');
   Add('VARIABLE id NUMBER INOUT');
   Add('INSERT INTO master (name) VALUES (:name) RETURNING id {INTO :id};');
   Add('INSERT INTO detail (fk_id, name) VALUES (:id, ''bbb'');');
 end;

Verwenden Sie den folgenden Code, um ein Makro zu definieren und zu referenzieren:

 DEF tab=Brands
 INSERT INTO !tab VALUES (1, 'Audi');
 INSERT INTO !tab VALUES (2, 'BMW');

Verwenden Sie den folgenden Code, um Argumente festzulegen und zu referenzieren:

 FDScript1.Arguments.Add('Brands');
 ...
 with FDScript1.SQLScripts[0].SQL do begin
   Add('INSERT INTO &1 VALUES (1, ''Audi'')');
   Add('INSERT INTO &1 VALUES (2, ''BMW'')');
 end;

Erhalten von Rückmeldungen

Um ein Ausführungsprotokoll zu erstellen, können Sie das Spooling wie im Delphi-Code mit den Optionen SpoolOutput und SpoolFileName oder wie in einem SQL-Skript mit den Anweisungen <code>SPOol <Name></code> oder <code>OUTput <Name></code> aktivieren. Der Inhalt der Spool-Ausgabe wird durch die Optionen EchoCommands, FeedbackCommands, AutoPrintParams, FeedbackScript, IgnoreError, Timing, ColumnHeadings, PageSize, ServerOutput gesteuert.

Mit der Komponente TFDGUIxScriptDialog ermöglichen Sie, dass eine Skriptausführungs-Engine mit einem Endbenutzer über ein Dialogfeld kommunizieren kann. Verwenden Sie für die Interaktion mit dem Endbenutzer-TFDScript Ereignisse, wie OnConsoleGet, OnConsolePut, OnGetText, OnPause usw. Dieses Dialogfeld stellt eine Standardimplementierung für diese Ereignisse bereit. Um den Ausführungsfortschritt anzuzeigen, muss TFDScript die gesamte Länge aller auszuführenden Skripte bekannt sein. Rufen Sie dazu die Methode ValidateAll vor Beginn der Skriptausführung auf.


Auflösen von Inkompatibilitäten

Die folgende Liste enthält bekannte Inkompatibilitäten von TFDScript mit den Originalhilfsprogrammen zu Skripterstellung:

  • Firebird ISQL arbeitet im Modus "Non-Autocommit". Für TFDScript/TFDConnection ist der Modus "Autocommit" standardmäßig aktiviert. Setzen Sie vor der Skriptausführung FDConnection.TxOptions.AutoCommit auf False, um eine höhere Kompatibilität zu erreichen. Oder führen Sie die Skriptanweisung SET AUTOCOMMIT OFF aus.
  • Microsoft ISQL gibt das Ergebnis der PRINT-Anweisung aus. TFDScript/TFDConnection gibt dies standardmäßig nicht aus. Setzen Sie ResourceOptions.ServerOutput auf True, oder führen Sie die Skriptanweisung SET SERVEROUTPUT ON aus, um die PRINT-Ausgabe zu aktivieren.