动态SQL

PostgreSQL 9.4.4 中文手册
上一页 | 上一级 | 章 33. ECPG - 在C中嵌入SQL | 下一页

# 33.5. 动态SQL

在许多情况下，应用要执行的具体的SQL语句在书写应用的时候就已经知道了。 不过，在某些情况下，SQL语句是在运行时或者由外部的数据提供的。 在这种情况下，我们不能直接在C代码嵌入SQL语句， 但是有个机制可以允许你调用放在一个字串变量里的任何SQL语句。

## 33.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`可以用于不返回结果集 （比如，DDL, `INSERT`, `UPDATE`, `DELETE`）的SQL语句。 你不能用这种方式执行检索数据（比如`SELECT`）的语句。 下一节将描述该如何做。

## 33.5.2. 执行具有输入参数的语句

执行任意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;

## 33.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`子句，也可以两个都有或者两个都没有。

如果查询希望返回多个结果行，那么使用游标，正如下面例子。 参阅第 33.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 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;

上一页 | 起始页 | 下一页
使用宿主变量 | 上一级 | pgtypes 库