Questions relatives aux scripts SQL (FireDAC)
Remonter à FAQ (FireDAC)
Cette rubrique liste des questions et réponses relatives à l'exécution de scripts SQL.
Q1 : Pourquoi ne puis-je pas utiliser un point-virgule à la fin d'une requête ? Si je le retire de la requête, cela fonctionne
R : Dans de nombreux dialectes de scripts SQL, le ';' est un délimiteur de commandes SQL et ne fait pas partie du langage SQL. Certains SGBD autorisent ce caractère à la fin des commandes SQL, d'autres pas. En d'autres termes, supprimez ';'.
Q2 : Certains SGBD (PG, Oracle, FB) ne me permettent d'exécuter qu'une seule instruction SQL, alors que SQLite permet l'exécution simultanée de plusieurs instructions. Pourquoi ?
R : Ceci est délibéré. La méthode ExecSQL transfère une commande SQL telle quelle à l'API du SGBD. Si un SGBD supporte les requêtes "groupées", il exécute la requête ; sinon, elle échoue. TFDScript permet d'exécuter les scripts SQL avec plusieurs commandes SQL et des commandes de contrôle de scripts.
Q3 : Même si j'ai plusieurs scripts, avec ExecuteAll seul le premier est exécuté
R : Le premier script est un script "root". Pour exécuter d'autres scripts, vous devez les appeler explicitement à partir du script "root". Par exemple :
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 exécute la commande de script suivante à partir de la position TFDScript.Position. ExecuteAll exécute le script en entier. Les méthodes ValidateAll / ValidateStep traitent également le script, mais n'exécutent pas les commandes SQL. L'appel à ValidateAll assigne une valeur à TFDScript.TotalJobSize. Par conséquent, l'appel suivant à ExecuteAll met correctement à jour TFDScript.TotalPct10Done, qui représente 10 % des commandes de script traitées.
Q4 : Existe-t-il une différence de performances entre (1) exécuter FDConnection.ExecSQL pour chaque instruction SQL (commande) et (2) exécuter FDScript.ExecuteAll ?
R : Le code d'exécution SQL derrière chacune de ces méthodes est le même. Il utilise la méthode IFDPhysCommand.Execute.
L'analyseur TFDScript est hautement optimisé, il reconnaît de nombreux aspects des dialectes SQL, tels qu'un PL/SQL Oracle (où ';' peut se trouver au milieu d'une commande) et permet un contrôle précis et flexible.
Par conséquent, si vous soumettez une commande à la fois à FDConnection.ExecSQL alors qu'il n'est pas nécessaire d'extraire ces commandes d'un script ou de quelque chose d'autre, ce sera alors la méthode la plus rapide. Si vous avez un script SQL dans un fichier, FDScript.ExecuteAll sera alors la méthode la plus rapide.
Q5 : Comment puis-je restaurer un script en cas d'échec ?
R : 1) Utilisez le contrôle de transaction FireDAC :
FDConnection1.StartTransaction;
try
FDScript1.ExecuteAll;
FDConnection1.Commit;
except
FDConnection1.Rollback;
raise;
end;
2) Utilisez un bloc PL/SQL pour Oracle ou des constructions similaires pour d'autres SGBD :
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) Utilisez TFDScript.OnError :
procedure TForm1.FDScript1Error(ASender: TObject;
const AInitiator: IFDStanObject; var AException: Exception);
begin
FDConnection1.Rollback;
end;
Q6 : Quand j'exécute le script ci-dessous sur FB, j'obtiens le message “Fin de commande inattendue ligne 3”. Comment résoudre ce problème ?
EXECUTE BLOCK
AS
DECLARE VARIABLE MYVAR VARCHAR(250);
BEGIN
...
END;
R : Pour exécuter un script comportant des blocs, vous devez changer le séparateur de commandes avant un bloc et éventuellement le rétablir après. Par exemple :
SET TERM #;
EXECUTE BLOCK
...
END;
#
SET TERM ;#