31.7. SQL dynamique
Dans de nombreux cas, les instructions SQL particulières qu'une
application doit exécuter sont connues au moment de l'écriture de
l'application. Néanmoins, dans certains cas, les instructions SQL
sont composées à l'exécution ou fournies par une source externe. Dans
ce cas, il n'est pas possible d'embarquer directement les
instructions SQL dans le code source C, mais il existe une
fonctionnalité permettant d'appeler des instructions SQL arbitraires
fournies par l'intermédiaire d'une variable de type chaîne.
La façon la plus simple d'exécuter une instruction SQL arbitraire est
d'utiliser la commande
EXECUTE
IMMEDIATE
. Par exemple :
EXEC SQL BEGIN DECLARE SECTION;
const char *stmt = "CREATE TABLE test1 (...);";
EXEC SQL END DECLARE SECTION;
EXEC SQL EXECUTE IMMEDIATE :stmt;
Les instructions de ce type ne peuvent pas être utilisées pour
récupérer des données (c'est-à-dire un
SELECT
).
Une façon plus puissante d'exécuter des instructions SQL arbitraires
est de les préparer une seule fois et de les exécuter ensuite aussi
souvent que nécessaire. Il est également possible de préparer une
version généralisée d'une instruction, puis d'exécuter les versions
spécifiques en substituant les paramètres. Lors de la préparation de
l'instruction, il suffit d'écrire des points d'interrogation aux
endroits où des paramètres seront substitués par la suite. Par
exemple :
EXEC SQL BEGIN DECLARE SECTION;
const char *stmt = "INSERT INTO test1 VALUES(?, ?);";
EXEC SQL END DECLARE SECTION;
EXEC SQL PREPARE mystmt FROM :stmt;
...
EXEC SQL EXECUTE mystmt USING 42, 'foobar';
Si l'instruction exécutée retourne des valeurs, il est nécessaire
d'ajouter une clause INTO :
EXEC SQL BEGIN DECLARE SECTION;
const char *stmt = "SELECT a, b, c FROM test1 WHERE a > ?";
int v1, v2;
VARCHAR v3;
EXEC SQL END DECLARE SECTION;
EXEC SQL PREPARE mystmt FROM :stmt;
...
EXEC SQL EXECUTE mystmt INTO v1, v2, v3 USING 37;
Une commande
EXECUTE
peut avoir une clause INTO, une clause
USING, les deux ou aucune.
Lorsqu'une instruction préparée n'est plus utile, il est préférable
de la désallouer :
EXEC SQL DEALLOCATE PREPARE name;