嵌入式SQL
概述
嵌入式SQL语言
- 将SQL语言嵌入到某一种高级语言中使用
- 这种高级语言,如C/C++, Java, PowerBuilder等,又称宿主语言(Host Language)
- 嵌入在宿主语言中的SQL与前面介绍的交互式SQL有一些不同的操作方式
下面以嵌入 C 语言为例,exec 关键字是为了让 C 语言编译器识别。
变量声明
在嵌入式SQL语句中可以出现宿主语言语句所使用的变量:
exec sql begin declare section;
char vSname[10], specName[10]=“张三”;
int vSage;
exec sql end declare section;
// 对 vSname 和 vSage 变量进行赋值(通过输入或直接赋值)
exec sql select Sname, Sage into:vSname, :vSage from Student
where Sname= :specName;
- 注意:
- 宿主程序的字符串变量长度应比字符型字段的长度多1个。因宿主程序的字符串尾部多一个终止符为‘\0‘,而程序中用双引号来描述。
- 宿主程序变量类型与数据库字段类型之间有些是有差异的,有些DBMS可支持自动转换,有些不能。
数据集与游标
单行结果处理与多行结果处理的差异
- 检索单行结果可将结果直接传送到宿主程序的变量中(Into)
EXEC SQL SELECT[ALL| DISTINCT] expression [, expression...]
INTO host-variable , [host-variable, ...]
FROM tableref [corr_name] [ , tableref [corr_name] ...]
WHERE search_condition;
示例
exec sql selectSname, Sage into:vSname, :vSagefromStudent where Sname = :specName ;
- 检索多行结果,则需使用游标(fetch-into)
- 游标是指向某检索记录集的指针
- 通过这个指针的移动,每次读一行,处理一行,再读一行… , 直至处理完毕
定义
- 声明游标
declare cursor
EXEC SQL DECLARE cursor_name CURSOR FOR
Subquery
[ORDER BY result_column [ASC| DESC][, result_column ...]
[FOR [ READ ONLY | UPDATE [OF columnname [, columnname...]]]];
示例
exec sql declare cur_studentcursor for
select Sno, Sname, Sclass from Student where Sclass= :vClassorder by Sno
for read only ;
- 打开和关闭
EXEC SQL OPEN cursor_name;
EXEC SQL CLOSE cursor_name;
- 数据读取
EXEC SQL FETCH cursor_name INTO host-variable , [host-variable, ...];
使用步骤
- 游标(Cursor)的使用需要先定义、再打开(执行)、接着一条接一条处理,最后再关闭
- 读一行操作是通过Fetch…into语句实现的:每一次Fetch, 都是先向下移动指针,然后再读取
- 记录集有结束标识EOF, 用来标记后面已没有记录了
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 FETCH
[ 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为正数向结束方向移动,为负数向开始方向移动
定位操作
- 定位删除
exec sql declare delcust cursor for
select cid from customers c wherec.city =‘harbin’and
not exists ( select* fromorders o whereo.cid = c.cid)
for update of cid;
exec sql open delcust
While (TRUE) {
exec sql fetch delcustinto :cust_id;
exec sql delete from customers where current of delcust; // 删除 delcust 游标的 current 位置元素
}
- 定位更新
exec sql update studentset custername = ‘cname’ where current of custcur ; // 更新 custcur 游标的 current 位置元素
动态构造
指根据输入,动态拼接 SQL,这也是嵌入式 SQL 的核心优势。
执行方式
- 动态SQL的两种执行方式
如SQL语句已经被构造在host-variable字符串变量中,则:
- 立即执行语句: 运行时编译并执行
EXEC SQL EXECUTE IMMEDIATE :host-variable; // host-variable 指 sql 字符串
- Prepare-Execute-Using语句:
- PREPARE语句先编译,编译后的SQL语句允许动态参数,
- EXECUTE语句执行,用USING语句将动态参数值传送给编译好的SQL语句
EXEC SQL PREPARE sql_temp FROM :host-variable; // host-variable 指 sql 字符串
......
EXEC SQL EXECUTE sql_temp USING :cond-variable
- 示例
#include <stdio.h>
#include "prompt.h"
exec sql include sqlca;
exec sql begin declare section;
char cust_id[5], sqltext[256], user_name[20], user_pwd[10];
exec sql end declare section;
char cid_prompt[ ] = "Name customer cid to be deleted: ";
int main(){
strcpy(sqltext, "delete from customers where cid = :dcid");
… …
while (prompt(cid_prompt, 1, cust_id, 4) >= 0) {
exec sql whenever not found goto no_such_cid;
exec sql prepare delcust from :sqltext; /* prepare statement */
exec sql execute delcust using :cust_id; /* using clause ... replaces ":n" above */
exec sql commit work; continue;
no_such_cid: printf("No cust %s in table\n",cust_id);
continue;
}
…
}
数据字典
数据字典通常存储的是数据库和表的元数据,让高级语言或者客户端可以获取,即模式本身的信息:
- 与关系相关的信息
- 关系名字
- 每一个关系的属性名及其类型
- 视图的名字及其定义
- 完整性约束
- 用户与账户信息,包括密码
- 统计与描述性数据:如每个关系中元组的数目
- 物理文件组织信息:
- 关系是如何存储的(顺序/无序/散列等)
- 关系的物理位置
- 索引相关的信息
数据字典的结构
- 也是存储在磁盘上的关系
- 专为内存高效访问设计的特定的数据结构