本章介绍PostgreSQL的嵌入式SQL包。最初它是为了与C一起工作而编写的。它也能与C++配合,但是它还不识别所有的C++结构。

35.1 概念

嵌入式SQL程序由编程语言(C)编写的代码混合特殊标记的SQL命令而成。

35.2 管理数据库连接

本节介绍如何打开、关闭和转换数据库连接。

35.2.1 连接到数据库服务

使用以下语句连接到数据库服务:

EXEC SQL CONNECT TO target [AS connection-name] [USER user-name];

35.2.2 选择连接

嵌入式SQL程序中的SQL语句默认在当前连接中执行。如果应用程序需要管理多个连接,则有两种方式实现:

  1. 显式为每个SQL语句选择连接:EXEC SQL AT connection-name SELECT ...;

  2. 执行切换当前连接的语句:EXEC SQL SET CONNECTION connection-name;

35.2.3 关闭连接

EXEC SQL DISCONNECT [connection];

35.3 运行SQL命令

嵌入式SQL应用程序中可运行任意SQL命令。

35.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;
返回单行的SELECT语句也可直接使用EXEC SQL执行,如果返回多行, 需要使用游标(cursor)。
EXEC SQL SELECT foo INTO :FooBar FROM table1 WHERE ascii = 'doodad';
查看参数配置:
EXEC SQL SHOW search_path INTO :var;

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

有关游标的更多信息,请参见DECLAREFETCH

35.3.3 管理事务

默认,仅当执行EXEC SQL COMMIT时语句才会提交。嵌入式SQL接口也可支持事务的自动提交(使用-t参数或EXEC SQL SET AUTOCOMMIT TO ON)。

 

可使用以下事务管理命令:

  • 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

  • EXEC SQL SET AUTOCOMMIT TO OFF

35.3.4 预编译语句

当在编译时传递到SQL语句的值还未知,或相同语句执行多次时,那么预编译语句就很有用处。语句使用PREPARE命令进行预编译。使用?进行未知值占位:

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

35.4 使用主变量

本节介绍如何在C程序与嵌入式SQL语句间通过主变量(host variables)传递数据。在嵌入式SQL程序中,SQL语句为C程序代码的客(guest),C程序为主(host)。所以C程序的变量称为主变量。

 

另一种在PostgreSQL后台进程与ECPG应用程序间交互数据的方式为SQL描述符,参见第35.7节

35.4.1 概览

在C程序和SQL语句间传递数据在嵌入式SQL中颇为简单。示例:

EXEC SQL INSERT INTO sometable VALUES (:v1, 'foo', :v2);

35.4.2 声明section

在传递数据的时候,需要为其声明一个特殊的标记区域(section),以便嵌入式SQL预处理器可以处理它。该区域以EXEC SQL BEGIN DECLARE SECTION;开始,以EXEC SQL END DECLARE SECTION;结束。在这之间,需要是标准的C变量声明,例如:

int x = 4;

char foo[16], bar[16];

也可用以下语法声明变量,这可以隐式创建一个声明区域:

EXEC SQL int i = 4;

35.4.3 检索查询结果

返回单行的使用SELECT,返回多行的使用FETCH。

示例:

/*
* 表DDL:
* CREATE TABLE test1 (a int, b varchar(50));
*/
EXEC SQL BEGIN DECLARE SECTION;
int v1;
VARCHAR v2;
EXEC SQL END DECLARE SECTION;
...
EXEC SQL SELECT a, b INTO :v1, :v2 FROM test;

EXEC SQL BEGIN DECLARE SECTION;
int v1;
VARCHAR v2;
EXEC SQL END DECLARE SECTION;
...
EXEC SQL DECLARE foo CURSOR FOR SELECT a, b FROM test;
...
do
{
...
EXEC SQL FETCH NEXT FROM foo INTO :v1, :v2;
...
} while (...);

35.4.4 类型匹配

数据类型需要在PostgreSQL数据类型和主语言变量类型(当前为C语言数据类型)之间转换。表35.1展示PostgreSQL数据类型与C数据类型的匹配:

35.4.5 处理非基础SQL数据类型

本节介绍如何在ECPG应用程序中处理非标准以及用户自定义的SQL级别的数据类型。

35.4.5.1 Array

ECPG不直接支持多维SQL级别的数组。如果使用查询分别访问数组的元素这就可避免在ECPG中使用数组。不过需要定义与元素数据类型匹配的主变量。

35.4.5.2 复合数据类型

ECPG不直接支持复合数据类型,但可提供与数组类似的折中解决方案。

35.4.5.3 用户定义的基础数据类型

ECPG不直接支持用户新定义的基础类型。但可以使用外部字符串表示以及主变量类型char[]或varchar[]。

35.4.6 指标

以上示例均无法处理null值。为处理null值,需要在每个主变量附加第二个变量:indicator(指标),其包含一个判断值是否为空的标记。

35.5 动态SQL

有时候,应用程序执行的SQL语句在执行时就可确定,但有的时候SQL语句确是在运行时或由外部提供。在这些情况下,无法直接将SQL语句嵌入到SQL源码中,但仍有解决方案。

35.5.1 执行没有结果集返回的语句

执行动态语句最简单的方式是执行EXECUTE IMMEDIATE。示例:

EXEC SQL BEGIN DECLARE SECTION;

const char *stmt = "CREATE TABLE test1 (...);";

EXEC SQL END DECLARE SECTION;

EXEC SQL EXECUTE IMMEDIATE :stmt;

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

35.5.3 执行有结果集的语句

执行返回单结果集的SQL语句,使用EXECUTE。使用INTO子句保留结果集。多行结果集,需要使用游标。

 

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐