On this page
35.5. 动态 SQL
在许多情况下,在编写应用程序时就知道了应用程序必须执行的特定 SQL 语句。但是,在某些情况下,SQL 语句在运行时组成或由外部源提供。在这些情况下,您不能将 SQL 语句直接嵌入到 C 源代码中,但是有一种功能可以让您调用在字符串变量中提供的任意 SQL 语句。
35 .5.1. 没有结果集的执行语句
执行任意 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
)的语句。下一节将介绍如何执行此操作。
35 .5.2. 使用 Importing 参数执行语句
执行任意 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;
35 .5.3. 执行带有结果集的语句
要在一个结果行中执行一条 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
子句,或者两者都具有。
如果期望查询返回一个以上的结果行,则应使用游标,如以下示例所示。 (有关光标的更多详细信息,请参见Section 35.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;