PostgreSQL 中文参考文档
🌐 英文原版 官方 ↗

34.5. 动态 SQL #

34.5.1. 执行没有结果集的语句
34.5.2. 执行带输入参数的语句
34.5.3. 执行带结果集的语句

在很多情况下,一个应用必须执行的特定 SQL 语句 在编写应用时就是已知的。但在某些情况下, SQL 语句是在运行时构造的,或由外部来源提供。 在这种情况下,你不能直接把 SQL 语句嵌入到 C 源代码中, 但有一种机制让你调用你在运行时提供的任意 SQL 语句, 这就是所谓的动态 SQL。

34.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;

34.5.2. 执行带输入参数的语句 #

执行任意 SQL 语句的一种更强大的方式是 只对它做一次预备,然后按照你的意愿多次执行预备好的语句。 也可以预备语句的一个通用版本, 然后通过替换参数来执行它的特定版本。 准备语句时,在希望稍后替换参数的位置写上问号 ?:

当你不再需要某个已准备语句时,应当释放它:

EXEC SQL DEALLOCATE PREPARE name;

34.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;
EXEC SQL END DECLARE SECTION;

EXEC SQL PREPARE mystmt FROM :stmt;
 ...
EXEC SQL EXECUTE mystmt INTO :v1, :v2, :v3 USING 37;

如果预期一个查询会返回多于一个结果行, 则应当像下面的示例那样使用游标。 (关于游标的更多细节见 Section 34.3.2。)

EXEC SQL BEGIN DECLARE SECTION;
char stmt[80];
int v1;
VARCHAR v2;
EXEC SQL END DECLARE SECTION;

strcpy(stmt, "SELECT a, b FROM test1 WHERE a > ?");
EXEC SQL PREPARE mystmt FROM :stmt;
EXEC SQL DECLARE cursor1 CURSOR FOR mystmt;
EXEC SQL OPEN cursor1 USING 37;
EXEC SQL WHENEVER NOT FOUND DO BREAK;
while (1)
{
    EXEC SQL FETCH cursor1 INTO :v1, :v2;
    ...
}
EXEC SQL CLOSE cursor1;