Fragen zu SQL-Skripten (FireDAC)
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 ;#