5.1.3 嵌入式SQL
5.1.3 嵌入式SQL
SQL
标准定义了嵌入SQL
到许多不同的语言中,例如C、C++、 Cobol
、 Pascal
、Java
、PL/I
和Fortran
。
宿主语言
SQL
查询所嵌入的语言被称为宿主语言,
嵌入是SQL
宿主语言中使用的SQL
结构被称为嵌入式SQL
.
使用宿主语言写出的程序可以通过嵌入式SQL
的语法访问和修改数据库中的数据。
嵌入式SQL
与JDBC
或ODBC
的主要区别
一个使用嵌入式SQL
的程序在编译前必须先由一个特殊的预处理器进行处理。嵌入的SQL
请求被宿主语言的声明以及允许运行时刻执行数据库访问的过程调用所代替。然后,所产生的程序由宿主语言编译器编译。这是嵌入式SQL
与JDBC
或ODBC
的主要区别。
- 在
JDBC
中,SQL
语句是在运行时被解释的(即使是利用预备语句特性对其进行准备也是如此) - 当使用嵌入式
SQL
时,一些SQL
相关的错误(包括数据类型错误**)可以在编译过程中被发现**。
EXEC SQL
语句
为使预处理器识别嵌入式SQL
请求,我们使用EXEC SQL
语句,格式如下
1 | EXEC SQL<嵌入式SQL语句>; |
嵌入式SQL
语法依赖于宿主语言
嵌入式SQL
的确切语法依赖于宿主语言。例如,当宿主语言是Cobol
时,语句中的分号用END-EXEC
来代替。
嵌入式SQL的相关的东西先省略,这里了解一下即可,后面用到再说.
我们在应用程序中合适的地方插入SQL INCLUDE SQLCA
语句,表示预处理器应该在此处插入特殊变量以用于程序和数据库系统间的通信。
在执行任何SQL
语句之前,程序必须首先连接到数据库。这是用下面语句实现的:
1 | EXEC SQL connect to server user user-name using password; |
这里, server
标识将要建立连接的服务器。
在嵌入的SQL
语句中可以使用宿主语言的变量,不过前面要加上冒号(:)以区别于SQL
变量。如此使用的变量必须声明在一个DECLARE
区段里,见下面的代码。不过声明变量的语法还是因循宿主语言的惯例。
1 | EXEC SQL BEGIN DECLARE SECTION; |
嵌入式SQL
语句的格式和本章描述的SQL
语句类似。但这儿要指出几点重要的不同之处。
为了表示关系査询,我们使用声明游标(declare cursor
)语句。然而这时并不计算查询的结果,而程序必须用open
和fetch
语句(本章后面将讨论)得到结果元组。接下来我们将看到,使用游标的方法与JDBC
中对结果集的迭代处理是很相似的。
考虑我们使用的大学模式。假设我们有一个宿主变量credit_amount
,声明方法如前所见,我们想找出学分高于credit_amount
的所有学生的名字。我们可写出查询语句如下:
1 | EXEC SQL declare c cursor for |
上述表达式中的变量c
被称为该查询的游标(cursor
)。我们使用这个变量来标识该查询,然后用open
语句来执行查询。
我们的例子中的open
语句如下:
1 | EXEC SQL open c; |
这条语句使得数据库系统执行这条查询并把执行结果存于一个临时关系中。当open
语句被执行的时候,宿主变量(credit_amount
)的值就会被应用到查询中。
如果SQL
查询出错,数据库系统将在SQL
通信区域(SQCA
)的变量中存储一个错误诊断信息。
然后我们利用一系列的fetch
语句把结果元组的值赋给宿主语言的变量。 fetch
语句要求结果关系的每一个属性有一个宿主变量相对应。在我们的查询例子中,需要一个变量存储I的值,另一个变量存储name
的值。假设这两个变量分别是si
和sn
,并且都已经在DECLARE
区段中被声明。那么以下语句:
1 | EXEC SQL fetch c into:si,:sn; |
产生结果关系中的一个元组。接下来应用程序就可以利用宿主语言的特性对si
和sn
进行操作了。
条单一的feth
请求只能得到一个元组。如果我们想得到所有的结果元组,程序中必须包含对所有元组执行的一个循环。嵌入式SoL
为程序员提供了对这种循环进行管理的支持。虽然关系在概念上是一个集合,查询结果中的元组还是有一定的物理顺序的。执行SQL
的open
语句后,游标指向结果的第一个元组。执行一条fetch
语句后,游标指向结果中的下一个元组。当后面不再有待处理的元组时,