Documentation PostgreSQL 9.3.25 > Interfaces client > ECPG SQL embarqué en C > SQL Dynamique | |
Utiliser des Variables Hôtes | Librairie pgtypes |
Fréquemment, les ordres SQL particuliers qu'une application doit exécuter sont connus au moment où l'application est écrite. Dans certains cas, par contre, les ordres SQL sont composés à l'exécution ou fournis par une source externe. Dans ces cas, vous ne pouvez pas embarquer les ordres SQL directement dans le code source C, mais il y a une fonctionnalité qui vous permet d'exécuter des ordres SQL que vous fournissez dans une variable de type chaîne.
La façon la plus simple d'exécuter un ordre SQL dynamique 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;
EXECUTE IMMEDIATE peut être utilisé pour des ordres SQL qui ne retournent pas de données (par exemple, LDD, INSERT, UPDATE, DELETE). Vous ne pouvez pas exécuter d'ordres qui ramènent des données (par exemple, SELECT) de cette façon. La prochaine section décrit comment le faire.
Une façon plus puissante d'exécuter des ordres SQL arbitraires est de les préparer une fois et d'exécuter la requête préparée aussi souvent que vous le souhaitez. Il est aussi possible de préparer une version généralisé d'une requête et d'ensuite en exécuter des versions spécifiques par substitution de paramètres. Quand vous préparez la requête, mettez des points d'interrogation où vous voudrez substituer des paramètres ensuite. 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';
Quand vous n'avez plus besoin de la requête préparée, vous devriez la désallouer:
EXEC SQL DEALLOCATE PREPARE name;
Pour exécuter une requête SQL avec une seule ligne de résultat, vous pouvez utiliser EXECUTE. Pour enregistrer le résultat, ajoutez une clause INTO.
EXEC SQL BEGIN DECLARE SECTION; const char *stmt = "SELECT a, b, c FROM test1 WHERE a > ?"; int v1, v2; VARCHAR v3[50]; 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.
Si une requête peut ramener plus d'un enregistrement, un curseur devrait être utilisé, comme dans l'exemple suivant. Voyez Section 33.3.2, « Utiliser des Curseurs » pour plus de détails à propos des curseurs.)
EXEC SQL BEGIN DECLARE SECTION; char dbaname[128]; char datname[128]; char *stmt = "SELECT u.usename as dbaname, d.datname " " FROM pg_database d, pg_user u " " WHERE d.datdba = u.usesysid"; EXEC SQL END DECLARE SECTION; EXEC SQL CONNECT TO testdb AS con1 USER testuser; EXEC SQL SELECT pg_catalog.set_config('search_path', '', false); EXEC SQL COMMIT; EXEC SQL PREPARE stmt1 FROM :stmt; EXEC SQL DECLARE cursor1 CURSOR FOR stmt1; EXEC SQL OPEN cursor1; EXEC SQL WHENEVER NOT FOUND DO BREAK; while (1) { EXEC SQL FETCH cursor1 INTO :dbaname,:datname; printf("dbaname=%s, datname=%s\n", dbaname, datname); } EXEC SQL CLOSE cursor1; EXEC SQL COMMIT; EXEC SQL DISCONNECT ALL;