嵌入式SQL语言:内容提要
4.1 嵌入式SQL语言简述
4.2嵌入式SQL语言的基本处理技巧
4.3 嵌入式程序中SQL语句的基本操作方式
4.4 动态SQL简介
4.1嵌入式SQL语言简述
-
交互式SQL语言的局限
现实中有些特别复杂的检索结果难以用一条交互式SQL语句完成,此时需要结合高级语言中经常出现的顺序、分支和循环结构来帮助处理
例如: 依据不同条件执行不同的检索操作等
If some-condition Then
SQL-Query1
Else
SQL-Query2
EndIf
再如: 控制检索操作执行的顺序
Do While some-condition
SQL-Query
EndDo
嵌入式SQL语言
将SQL语言嵌入到某一种高级语言中使用
这种高级语言,如C/C++, Java等,又称宿主语言
嵌入在宿主语言中的SQL与前面介绍的交互式SQL有一些不同的操作方式嵌入式SQL语言与交互式SQL语言
交互式SQL语言:
select Sname, Sage from Student
where Sname=‘张三’;
嵌入式SQL语言: 以宿主语言C语言为例
exec sql
select Sname, Sage into :vSname, :vSage from Student
where Sname=‘张三’;
-
上述嵌入式SQL语言的特性
exec sql引导SQL语句:
提供给C编译器,以便对SQL语句预编译成C编译器可识别的语句
增加 into 子句:
该子句用于指出接收SQL语句检索结果的程序变量
由冒号引导的程序变量:
如: ‘:vSname’, ‘:vSage’
4.2嵌入式SQL语言的基本处理技巧
4.2.1变量的声明与使用
- 在嵌入式SQL语句中可以出现宿主语言语句所使用的变量
exec sql
select Sname, Sage into :vSname, :vSage from Student
where Sname=‘张三’;
- 这些变量需要特殊的声明,如下所示
exec sql
begin declare section;
char vSname[10], specName[10]=“张三”;
int vSage;
exec sql
end declare section;
PS:要注意宿主程序的字符串变量长度应比字符型字段的长度多1个,因宿主程序的字符串尾部多一个终止符为‘\0‘,而程序中用双引号来描述
-
变量的使用
声明的变量,可以在宿主程序中赋值,然后传递给SQL语句的where等子句中,以使SQL语句能够按照指定的要求(可变化的)进行检索
exec sql
begin declare section;
char vSname[10], specName[10]=“张三”;
int vSage;
exec sql
end declare section;
exec sql
select Sname, Sage into :vSname, :vSage from Student
where Sname = :specName
4.2.2程序与数据库的连接与断开
-
数据库连接
在嵌入式SQL程序执行之前,首先要与数据库进行连接 - SQL标准中建议的连接语法为
exec sql
connect to target-server as
connect-name user user-name;
或
exec sql connect to default;
- Oracle中数据库连接
connect :user_name identified by:user_pwd;
- DB2 UDB中数据库连接:
connect to mydbuser :user_name using :user_pwd
- 数据库断开
- SQL标准中建议的断开连接的语法为
exec sql disconnect connect-name;
或
exec sql disconnect current;
- Oracle中断开数据库连接
exec sql commit release;
或
exec sql rollback release;
- DB2 UDB中断开数据库连接
exec sql connect reset;
4.2.3 SQL结果的提交与撤消
-
简述
SQL语句在程序执行过程中,必须有提交和撤消语句才能确认其操作结果 - SQL结果的提交
exec sql commit work;
- SQL结果的撤消
exec sql rollback work;
为此
很多DBMS都设计了捆绑提交/撤消与断开连接在一起的语句,以保证在断开连接之前使用户确认提交或撤消先前的工作
- 例如Oracle中:
exec sql commit release;
或
exec sql rollback release;
4.2.4单行结果处理与多行结果处理的差异Into子句与游标(Cursor)
-
单行结果
单行检索结果的处理,可以直接使用
select...into...
嵌入式select语句中引入into子句,只能保留和处理单行结果
exec sql
select Sno, Sname, Sclass into :vSno, :vSname, :vSclass
from Student
where Sname=‘张三’;
多行检索结果的处理则需使用游标
读一行操作是通过Fetch...into语句实现的:
每一次Fetch, 都是先向下移动指针,然后再读取
记录集有结束标识EOF, 用来标记前面和后面已没有记录了游标检索示例
exec sql
declare cur_student cursor for
select Sno, Sname, Sclassfrom Student
where Sclass=‘035101’ ;
#检索出所有calss为035101的元组
exec sql open cur_student;
exec sql fetch cur_student
into :vSno, :vSname, :vSclass;......
exec sql close cur_student;
PS:游标可以定义一次,多次打开(多次执行),多次关闭
4.2.5 状态捕获及其处理
简述
状态,是嵌入SQL语句的执行状态,尤其指一些出错状态;有时程序需要知道这些状态并对这些状态进行处理设置SQL通信区:
一般在嵌入式SQL程序的开始处便设置
exec sql include sqlca;
PS: SQL通信区: SQLCA
SQLCA是一个已被声明过的具C结构形式的内存信息区,其中的成员变量用来记录SQL语句执行的状态,便于宿主程序读取与处理
SQLCA是DBMS(执行SQL语句)与宿主程序之间交流的桥梁之一
-
设置状态捕获语句:
在嵌入式SQL程序的任何位置都可设置;可多次设置;但有作用域
exec sql whenever
sqlerror goto report_error;
PS:
exec sql whenever condition action;
Whenever语句的作用是设置一个“条件陷阱”, 该条语句会对其后面的所有由Exec SQL语句所引起的对数据库系统的调用自动检查它是否满足条件(由condition指出)
SQLERROR:
检测是否有SQL语句出错。其具体意义依赖于特定的DBMS
NOT FOUND:
执行某一SQL语句后,没有相应的结果记录出现
SQLWARNING:
不是错误,但应引起注意的条件
condition:如果满足condition 则要采取一些动作(由action指出)
CONTINUE:
忽略条件或错误,继续执行
GOTO
标号:转移到标号所指示的语句,去进行相应的处理
STOP:
终止程序运行、撤消当前的工作、断开数据库的连接
DO函数或CALL函数:
调用宿主程序的函数进行处理,函数返回后从引发该condition的ExecSQL语句之后的语句继续进行
-
状态处理语句:
某一段程序以应对SQL操作的某种状态
report_error:
exec sql rollback
4.2.6典型DBMS系统记录状态信息的三种方法
- 状态记录:sqlcode、sqlca.sqlcode、sqlstate
sqlcode:
典型DBMS都提供一个sqlcode变量来记录其执行sql语句的状态:
sqlcode== 0, successful call;
sqlcode< 0, error, e.g., from connect, database does not exist;
sqlcode>0, warning, e.g., no rows retrieved from fetch
sqlca.sqlcode:一个存储信息的对象,包
sqlca.sqlcode: 支持sqlca的产品一般要在sqlca中填写sqlcode来记录上述信息; 除此而外,sqlca还有其他状态信息的记录
sqlca是一个存储区域,将统计和错误从应用程序传递到数据库服务器再传回应用程序的每个数据库请求会使用它;
sqlca用作应用程序到数据库的通信链接的句柄。它会被传递到需要与数据库服务器进行通信的所有数据库库函数中;
它会在所有嵌入式SQL语句上被隐式传递
sqlstate: 有些DBMS提供的记录状态信息的变量是sqlstate或sqlca.sqlstate
4.3 嵌入式程序中SQL语句的基本操作方式
4.3.1 Select语句的基本操作
exec sql select Sname, Sage
into :vSname, :vSage from Student
where Sname= :specName;
4.3.2 Delete语句的基本操作
- 查找删除与定位删除:
查找删除:
exec sql delete from customers c
where c.city= ‘harbin’ and not exists
( select *from orders o where o.cid= c.cid);
定位删除:
exec sql declare delcust cursor
for select cid from customers c
where c.city=‘harbin’ and not exists
( select *from orders o where o.cid= c.cid)
for update of cid;
exec sql open delcust
While (true)
{
exec sql fetch delcust
into :cust_id;exec sql
delete from customers
where current of delcust;
}
4.3.3 Update语句的基本操作
- 查找更新与定位更新:
查找更新:
exec sql
update students set sclass= ‘035102’
where s.sclass= ‘034101’
定位更新:
exec sql declare stud cursor
for select * from student s
where s.sclass=‘034101’
for update of sclass;
exec sqlopen stud
While (true)
{
exec sqlfetch stud
into :vSno, :vSname, :vSclass;
exec sql
update student set sclass= ‘035102’
where current of stud; }
4.3.6 Insert语句的基本操作
exec sql
insert into student ( sno, sname, sclass)
values (‘03510128’, ‘张三’, ‘035101’) ;
4.3.5 Cursor相关语句的基本操作
exec sql declare cur_student cursor
for select Sno, Sname, Sclass from Student
where Sclass= :vClass
order by Snofor read only ;
- Cursor的打开和关闭:
open cursor / close cursor
exec sql open cursor_name;
exec sql close cursor_name;
- 数据读取:Fetch
exec sql declare cur_student cursor
for select Sno, Sname, Sclass from Student
where Sclass= :vClass
order by Snofor read only ;
exec sql open cur_student;
exec sql fetch cur_student
into :vSno, :vSname, :vSage
exec sql close cur_student;
- 可滚动cursor示例:
exec sq lfetch
[next | prior | first | last | [absolute | relative]value_spec]
from cursor_name
into host-variable [, host-variable ...];
next:向结束方向移动一条;
prior:向开始方向移动一条;
first:回到第一条;
last:移动到最后一条;
absolutvalue_spec:定向检索指定位置的行,value_spec由1至当前记录集最大值;
relativevalue_spec:相对当前记录向前或向后移动,value_spec为正数向结束方向移动,为负数向开始方向移动
4.4 动态SQL简介
4.4.1动态SQL的概念和作用
4.4.2动态SQL的两种执行方式
4.4.3更为复杂的动态SQL