Fragen zu SQL-Skripten (FireDAC)

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu FAQ (FireDAC)

Dieses Thema enthält eine Liste mit Fragen und Antworten zur Ausführung von SQL-Skripten.

F1: Warum kann ich am Ende einer Abfrage kein Semikolon verwenden? Wenn ich es aus der Abfrage entferne, funktioniert sie.

A: Das ";" ist in vielen SQL-Skriptdialekten ein Trennzeichen für die SQL-Anweisungen und kein Teil der SQL-Sprache. Bei einigen DBMSs ist ";" am Ende von SQL-Anweisungen zulässig, bei anderen nicht. Mit anderen Worten, entfernen Sie das ";" einfach.

F2: In einigen DBMSs (Postgres, Oracle, Firebird) ist es möglich, nur eine SQL-Anweisung auszuführen, aber SQLite lässt die gleichzeitige Ausführung mehrerer Anweisungen zu. Warum ist das so?

A: Das ist so vorgesehen. Die Methode ExecSQL überträgt eine SQL-Anweisung direkt an die DBMS-API. Wenn ein DBMS "Stapelabfragen" unterstützt, wird die Abfrage ausgeführt, andernfalls schlägt sie fehl. TFDScript ermöglicht die Ausführung von SQL-Skripten mit mehreren SQL-Anweisungen und Skriptsteuerungsbefehlen.

F3: Auch bei mehreren Skripten mit ExecuteAll wird nur die erste ausgeführt.

A: Das erste Skript ist das "root"-Skript. Um andere Skripte auszuführen, müssen Sie sie explizit vom "root"-Skript aus aufrufen. Zum Beispiel:

 with FDScript1.SQLScripts do begin
   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;

ExecuteStep führt die nächste Skriptanweisung ab TFDScript.Position aus. ExecuteAll führt das gesamte Skript aus. Die Methoden ValidateAll/ValidateStep verarbeiten das Skript auch, führen aber keine SQL-Anweisungen aus. Der Aufruf von ValidateAll weist TFDScript.TotalJobSize einen Wert zu. Daher aktualisiert der nächste ExecuteAll-Aufruf TFDScript.TotalPct10Done korrekt, was für 10 % der verarbeiteten Skriptanweisungen steht.

F4: Besteht ein Leistungsunterschied zwischen (1) dem Ausführen von FDConnection.ExecSQL für jede SQL-Anweisung und (2) dem Ausführen von FDScript.ExecuteAll?

A: Der diesen Methoden zugrunde liegende Code für die SQL-Ausführung ist derselbe. Sie verwenden die Methode IFDPhysCommand.Execute.

Der TFDScript-Parser ist hochoptimiert, er erkennt viele SQL-Dialektaspekte, wie Oracle PL/SQL (wobei ";" in der Mitte der Anweisung stehen kann), und ermöglicht eine präzise und flexible Steuerung.

Wenn Sie also jeweils nur eine Anweisung an FDConnection.ExecSQL übergeben und diese Anweisung nicht aus einem Skript (oder etwas Ähnlichem) extrahiert werden muss, dann ist dies die schnellste Methode. Wenn sich ein SQL-Skript in einer Datei befindet, dann ist FDScript.ExecuteAll die schnellste Methode.

F5: Wie kann ich die durch ein Skript hervorgerufenen Änderungen zurücksetzen, wenn das Skript fehlschlägt?

A: 1) Verwenden Sie das FireDAC-Transaktionssteuerelement:

 FDConnection1.StartTransaction;
 try
   FDScript1.ExecuteAll;
   FDConnection1.Commit;
 except
   FDConnection1.Rollback;
   raise;
 end;

2) Verwenden Sie den PL/SQL-Block für Oracle oder ähnliche Konstruktionen für andere DBMSs:

 begin
   insert into u_btk.t_test values (1, sysdate);
   insert into u_btk.t_test values (2, sysdate);
   insert into u_btk.t_test values (1, sysdate);
   commit;
 exception
   when others then
     rollback;
     raise;
 end;

3) Verwenden Sie TFDScript.OnError:

 procedure TForm1.FDScript1Error(ASender: TObject;
   const AInitiator: IFDStanObject; var AException: Exception);
 begin
   FDConnection1.Rollback;
 end;

F6: Wenn ich das folgende Skript in Firebird ausführe, erhalte ich die Meldung “Unerwartetes Ende der Anweisungszeile 3". Wie kann ich das beheben?

 EXECUTE BLOCK
 AS
 DECLARE VARIABLE MYVAR VARCHAR(250);
 BEGIN
 ...
 END;

A: Um ein Skript mit Blöcken auszuführen, müssen Sie das Anweisungstrennzeichen vor einem Block ändern und optional danach wieder zurücksetzen. Zum Beispiel:

 SET TERM #;
 EXECUTE BLOCK
 ...
 END;
 
 #
 
 SET TERM ;#