# 36.3.运行SQL命令

36.3.1. 执行SQL语句

36.3.2. 使用游标

36.3.3. 管理交易

36.3.4. 准备好的声明

任何SQL命令都可以在嵌入式SQL应用程序中运行。下面是一些如何做到这一点的例子。

# 36.3.1.执行SQL语句

创建表:

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

插入行:

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

删除行:

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

更新:

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

选择返回单个结果行的语句也可以使用执行SQL直接地要处理多行的结果集,应用程序必须使用游标;看见第36.3.2节在下面(作为一种特殊情况,应用程序可以一次将多行提取到数组主机变量中;请参阅。)第36.4.4.3.1节.)

单行选择:

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

此外,还可以使用显示命令:

EXEC SQL SHOW search_path INTO :var;

形式的象征:*某物*宿主变量也就是说,它们指的是C程序中的变量。这些问题在本文中有详细的解释第36.4节.

# 36.3.2.使用游标

要检索包含多行的结果集,应用程序必须声明一个游标并从游标中获取每一行。使用游标的步骤如下:声明游标,打开它,从游标中提取一行,重复,最后关闭它。

选择使用光标:

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;

有关声明游标的更多详细信息,请参阅声明; 有关从光标获取行的更多详细信息,请参阅取来.

# 笔记

ECPG声明命令实际上不会导致将语句发送到PostgreSQL后端。光标在后端打开(使用后端的声明命令)在打开命令被执行。

# 36.3.3.管理交易

在默认模式下,只有在执行SQL提交已发布。嵌入式SQL接口还支持通过自动提交事务(类似于psql的默认行为)-t命令行选项ecpg(见ecpg)或者通过EXEC SQL将自动提交设置为打开陈述在自动提交模式下,每个命令都会自动提交,除非它位于显式事务块内。可以使用以下命令显式关闭此模式:EXEC SQL将自动提交设置为关闭.

以下事务管理命令可用:

执行SQL提交

提交正在进行的事务。

执行SQL回滚

回滚正在进行的事务。

EXEC SQL准备事务交易id

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

EXEC SQL提交已准备就绪交易id

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

EXEC SQL回滚已准备就绪交易id

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

EXEC SQL将自动提交设置为打开

启用自动提交模式。

EXEC SQL将自动提交设置为关闭

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

# 36.3.4.准备好的声明

当要传递给SQL语句的值在编译时是未知的,或者同一语句将被多次使用时,准备好的语句可能会很有用。

该语句是使用命令准备的准备.对于未知的值,请使用占位符“?”:

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

如果语句返回一行,应用程序可以调用处决之后准备要执行该语句,请使用使用条款:

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

如果语句返回多行,应用程序可以使用基于准备好的语句声明的游标。要绑定输入参数,必须使用使用条款:

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;

更多关于准备看见准备.另见第36.5节有关使用占位符和输入参数的详细信息。