33.3. 运行SQL命令
在嵌入的SQL应用中可以运行任何SQL命令。下面是一些如何使用它们的例子。
33.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;
可以通过EXEC SQL
直接执行返回一个结果行的SELECT
语句。为了处理多行结果集,应用程序必须使用游标; 参阅Section 33.3.2。(特殊情况下,应用程序可以一次读取多行到数组宿主变量中; 参阅Section 33.4.4.3.1。)
单行select:
EXEC SQL SELECT foo INTO :FooBar FROM table1 WHERE ascii = 'doodad';
同时,可以使用SHOW
命令检索配置参数:
EXEC SQL SHOW search_path INTO :var;
形如:``_something_
这样的记号是宿主变量,也就是说,他们指向C程序中的变量。 在Section 33.4中有解释。
33.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;
关于游标声明的更多细节,请参阅DECLARE,关于 FETCH
命令的细节请参阅FETCH。
Note: ECPG
DECLARE
命令实际上不会造成语句被发送到PostgreSQL后端。 当执行OPEN
命令时, 在后端(使用后端的DECLARE
命令)打开游标。
33.3.3. 管理事务
在缺省模式下,语句只有在EXEC SQL COMMIT
发出的时候才提交, 嵌入的SQL接口也支持事务的自动提交(类似libpq的行为), 方法是通过给ecpg
(见ecpg) 增加命令行选项-t
, 或者是通过EXEC SQL SET AUTOCOMMIT TO ON
语句。 在自动提交模式里,每条命令都是自动提交的, 除非它们包围在一个明确的事务块里。 这个模式可以用EXEC SQL SET AUTOCOMMIT TO OFF
明确地关闭。
有以下事务管理命令可用:
EXEC SQL COMMIT
提交正在进行的事务。
EXEC SQL ROLLBACK
回滚正在进行的事务。
EXEC SQL SET AUTOCOMMIT TO ON
启动自动提交模式。
SET AUTOCOMMIT TO OFF
禁用自动提交模式。这是缺省的。
33.3.4. 预备语句
当编译时间不知道该值已被传递给SQL语句,或者同一语句将使用多次, 那么预备语句是有帮助的。
使用命令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;
/* 当结果集达到最后时,打破while循环 */
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 33.5 获得关于占位符和输入参数的更多详情。