在很多情况下,应用程序必须执行的特定 SQL 语句在编写应用程序时已知。但在某些情况下,SQL 语句是在运行时编制或由外部来源提供的。在这些情况下,您不能将 SQL 语句直接嵌入到 C 源代码中,但有一个设施允许您调用您在字符串变量中提供的任意 SQL 语句。
执行任意 SQL 语句的最简单方法是使用命令 EXECUTE IMMEDIATE
。例如
EXEC SQL BEGIN DECLARE SECTION; const char *stmt = "CREATE TABLE test1 (...);"; EXEC SQL END DECLARE SECTION; EXEC SQL EXECUTE IMMEDIATE :stmt;
EXECUTE IMMEDIATE
可用于不返回结果集的 SQL 语句(例如,DDL、INSERT
、UPDATE
、DELETE
)。您不能通过这种方式执行检索数据的语句(例如,SELECT
)。下一节将介绍如何执行此类语句。
执行任意 SQL 语句的更有效方法是准备一次该语句,并尽可能多地执行已准备语句。还可以准备语句的通用版本,然后通过替换参数来执行特定版本。在准备语句时,在您想要稍后替换参数的位置书写问号。例如
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';
当您不再需要已准备语句时,您应该释放该语句
EXEC SQL DEALLOCATE PREPARE name
;
要执行单结果行的 SQL 语句,可以使用 EXECUTE
。要保存结果,添加 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;
EXECUTE
命令可以具有 INTO
子句、USING
子句、同时具有这两个子句或都不具有这两个子句。
如果预计查询返回多个结果行,则应使用游标,如下面的示例所示。(有关游标的更多详细信息,请参阅 第 34.3.2 节。)
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;