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

34.3. 执行 SQL 命令 #

34.3.1. 执行普通 SQL 语句
34.3.2. 使用游标
34.3.3. 事务管理
34.3.4. 预备语句

任何 SQL 命令都可以在嵌入式 SQL 应用内部执行。 下面是一些这样做的示例。

34.3.1. 执行普通 SQL 语句 #

Creating a table:

EXEC SQL CREATE TABLE foo (number integer, ascii char(16));
EXEC SQL CREATE UNIQUE INDEX num1 ON foo(number);
EXEC SQL COMMIT;

Inserting rows:

EXEC SQL INSERT INTO foo (number, ascii) VALUES (9999, 'doodad');
EXEC SQL COMMIT;

Deleting rows:

EXEC SQL DELETE FROM foo WHERE number = 9999;
EXEC SQL COMMIT;

Updates:

EXEC SQL UPDATE foo
    SET ascii = 'foobar'
    WHERE number = 9999;
EXEC SQL COMMIT;

返回单一结果行的 SELECT 语句 也可以直接使用 EXEC SQL 执行。 要处理包含多行的结果集,应用必须使用游标; 见下文的 Section 34.3.2。 (作为一种特殊情况,应用可以一次把多行抓取到一个 数组宿主变量中;见 Section 34.4.4.3.1。)

Single-row select:

EXEC SQL SELECT foo INTO :FooBar FROM table1 WHERE ascii = 'doodad';

此外,也可以用 SHOW 命令检索一个配置参数:

EXEC SQL SHOW search_path INTO :var;

形如 :something 的记号是宿主变量, 也就是说它们引用 C 程序中的变量。 它们在 Section 34.4 中解释。

34.3.2. 使用游标 #

要检索包含多行的结果集,应用必须声明一个游标, 然后从游标中逐行抓取。使用游标的步骤是: 声明游标、打开它、从游标抓取一行、重复这一过程, 最后关闭它。

Select using cursors:

EXEC SQL DECLARE foo_bar CURSOR FOR
    SELECT number, ascii FROM foo
    ORDER BY ascii;
EXEC SQL OPEN foo_bar;
EXEC SQL FETCH foo_bar INTO :FooBar, DooDad;
...
EXEC SQL CLOSE foo_bar;
EXEC SQL COMMIT;

关于声明游标的更多细节见 DECLARE; 关于从游标抓取行的更多细节见 FETCH。

Note

ECPG 的 DECLARE 命令实际上并不会 向 PostgreSQL 后端发送语句。游标是在 OPEN 命令执行的时刻 在后端(使用后端的 DECLARE 命令)打开的。

34.3.3. 事务管理 #

在默认模式下,只有发出 EXEC SQL COMMIT 时语句才会被提交。嵌入式 SQL 接口也支持事务的自动提交 (类似于 psql 的默认行为), 方法是给 ecpg 传递 -t 命令行选项(见 ecpg), 或使用 EXEC SQL SET AUTOCOMMIT TO ON 语句。在自动提交模式下, 每条命令都会被自动提交,除非它位于一个显式事务块内。 该模式可以用 EXEC SQL SET AUTOCOMMIT TO OFF 显式关闭。

以下事务管理命令可用:

EXEC SQL COMMIT #

提交一个进行中的事务。

EXEC SQL ROLLBACK #

回滚一个进行中的事务。

EXEC SQL PREPARE TRANSACTION transaction_id #

为两阶段提交准备当前事务。

EXEC SQL COMMIT PREPARED transaction_id #

提交一个处于已准备状态的事务。

EXEC SQL ROLLBACK PREPARED transaction_id #

回滚一个处于已准备状态的事务。

EXEC SQL SET AUTOCOMMIT TO ON #

Enable autocommit mode.

EXEC SQL SET AUTOCOMMIT TO OFF #

禁用自动提交模式。这是默认设置。

34.3.4. 预备语句 #

当要传给某条 SQL 语句的值在编译时还不知道, 或者同一条语句会被使用很多次时, 预备语句(prepared statement)就会很有用。

语句通过 PREPARE 命令预备。 对于还不知道的值,使用占位符 “?”:

EXEC SQL PREPARE stmt1 FROM "SELECT oid, datname FROM pg_database WHERE oid = ?";

如果语句只返回一行,应用可以在 PREPARE 之后调用 EXECUTE 来执行该语句, 并通过 USING 子句提供占位符的实际值:

EXEC SQL EXECUTE stmt1 INTO :dboid, :dbname USING 1;

如果语句返回多行,应用可以基于该预备语句声明一个游标。 要绑定输入参数,必须用 USING 子句打开游标:

EXEC SQL PREPARE stmt1 FROM "SELECT oid,datname FROM pg_database WHERE oid > ?";
EXEC SQL DECLARE foo_bar CURSOR FOR stmt1;

/* when end of result set reached, break out of while loop */
EXEC SQL WHENEVER NOT FOUND DO BREAK;

EXEC SQL OPEN foo_bar USING 100;
...
while (1)
{
    EXEC SQL FETCH NEXT FROM foo_bar INTO :dboid, :dbname;
    ...
}
EXEC SQL CLOSE foo_bar;

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

EXEC SQL DEALLOCATE PREPARE name;

关于 PREPARE 的更多细节见 PREPARE。关于使用占位符 和输入参数的更多细节另见 Section 34.5。