前言
正文
一、嵌入式SQL
以宿主语言C语言为例
exec sql select Sname, Sage into :vSname, :vSage from Student
where Sname=‘张三’ ;
- 典型特点
---- exec sql引导SQL语句: 提供给C编译器,以便对SQL语句预编译成C编译器
可识别的语句
---- 增加一 into子句: 该子句用于指出接收SQL语句检索结果的程序变量
---- 由冒号引导的程序变量,如: ‘:vSname’, ‘:vSage’
变量的声明与使用
在嵌入式SQL语句中可以出现宿主语言语句所使用的变量:
exec sql select Sname, Sage into :vSname, :vSage from
Student where Sname= :specName;
这些变量需要特殊的声明:
exec sql begin declare section;
char vSname[10], specName[10]=“张三”;
int vSage;
exec sql end declare section;
程序与数据库的连接和断开
- SQL标准中建议的连接语法为:
execsql connecttotarget-server asconnect-name useruser-name;
或
execsql connecttodefault;
- Oracle中数据库连接:
execsql connect:user_name identified by :user_pwd;
- DB2 UDB中数据库连接:
execsql connecttomydb user:user_name using:user_pwd;
在嵌入式SQL程序执行之后,需要与数据库断开连接
- 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;
exec sql disconnect current;
SQL执行的提交与撤消
SQL语句在执行过程中,必须有提交和撤消语句才能确认其操作结果
- SQL执行的提交:
execsql commitwork;
- SQL执行的撤消:
execsql rollbackwork;
- 为此,很多DBMS都设计了捆绑提交/撤消与断开连接在一起的语句,以保证在断开连接之前使用户确认提交或撤消先前的工作,例如Oracle中:
execsql commitrelease;
或
execsql rollbackrelease;
示例
二、数据集与游标
检索多行结果,则需使用游标(Cursor)
- 游标是指向某检索记录集的指针
- 通过这个指针的移动,每次读一行,处理一行,再读一行… , 直至处理完毕
- 读一行操作是通过Fetch…into语句实现的:每一次Fetch, 都是先向下
移动指针,然后再读取 - 记录集有结束标识EOF, 用来标记后面已没有记录了
游标(Cursor)的使用
- 游标(Cursor)的使用需要先定义、再打开(执行)、接着一条接一条处理,最后再关闭
//定义
exec sql declare cur_student cursor for
select Sno, Sname, Sclass from Student where Sclass=‘035101’ ;
//打开
exec sql open cur_student;
//推进
exec sql fetch cur_student into :vSno, :vSname, :vSclass;
… …
//关闭
exec sql close cur_student;
- 游标可以定义一次,多次打开(多次执行),多次关闭
示例
exec sql declare cur_student cursor for
select Sno, Sname, Sclass from Student where Sclass= :vClass
order by Sno for read only ;
exec sql open cur_student;
…
exec sql fetch cur_student into :vSno, :vSname, :vSage
…
exec sql close cur_student;
可滚动游标
- 可滚动游标是可使游标指针在记录集之间灵活移动、使每条记录可以反复被访问的一种游标
NEXT向结束方向移动一条; PRIOR向开始方向移动一条;FIRST回到第一条;LAST移动到最后一条;ABSOLUTvalue_spec定向检索指定位置的行,value_spec由1至当前记录集最大值;RELATIVEvalue_spec相对当前记录向前或向后移动,value_spec为正数向结束方向移动,为负数向开始方向移动 - 可滚动游标移动时需判断是否到结束位置,或到起始位置
- 可通过判断是否到EOF位置(最后一条记录的后面),或BOF位置(起始记
录的前面) - 如果不需区分,可通过whenevernotfound语句设置来检测
- 可通过判断是否到EOF位置(最后一条记录的后面),或BOF位置(起始记
数据库记录的删除
一种是查找删除(与交互式DELETE语句相同),一种是定位删除
示例:查找删除
普通SQL语句一样的删除
exec sql delete from customers c where c.city = ‘Harbin’ and
not exists ( select * from orders o where o.cid = c.cid);
示例:定位删除
加current of 游标名
表示删除游标所指的当前内容
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 ; }
数据库记录的更新
一种是查找更新(与交互式Update语句相同),一种是定位更新
示例:查找更新
exec sql update student s 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 sql open stud
While (TRUE) {
exec sql fetch stud into :vSno, :vSname, :vSclass;
exec sql update student set sclass = ‘035102’ where current of
stud ; }
数据库记录的插入
只有一种类型的插入语句
示例:插入语句
exec sql insert into student ( sno, sname, sclass)
values (‘03510128’, ‘张三’, ‘035101’) ;
示例:插入语句
exec sql insert into masterstudent ( sno, sname, sclass)
select sno, sname, sclass from student;
示例:宿主语言与SQL结合的过程性控制
求数据库中某一列位于中值的那一行
三、状态捕获及错误处理机制
嵌入式 SQL程序中,状态捕获及处理有三部分构成
- 设置SQL通信区:一般在嵌入式SQL程序的开始处便设置
exec sql include sqlca;
- 设置状态捕获语句:在嵌入式SQL程序的任何位置都可设置;可多次设置;
但有作用域exec sql whenever sqlerror goto report_error;
- 状态处理语句:某一段程序以应对SQL操作的某种状态
report_error: exec sql rollback;
状态捕获语句Whenever的作用范围是其后的所有Exec SQL语句,一直到程序中出现另一条相同条件的Whenever语句为止,后面的将覆盖前面的。
- S1标号指示的语句受第二个Whenever语句约束。
- 注意:作用域是语句在程序中的位置,而不是控制流程(因是预编译程序处
理条件陷阱)