Questions relatives aux scripts SQL (FireDAC)

De RAD Studio
Aller à : navigation, rechercher

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