《数据库原理及应用幻灯片.ppt》由会员分享,可在线阅读,更多相关《数据库原理及应用幻灯片.ppt(29页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、数据库原理及应用第1页,共29页,编辑于2022年,星期六l 嵌入式SQL是指在程序内执行的SQL语句,它强调这些SQL语句是“嵌入”在编程语言的常规语句中的。Java中标准的嵌入式SQL称为SQLJ,可以在ORACLE、INFORMIX、DB2 UDB中使用,也可以通过JDBC在Java中使用,JDBC是标准Java的一部分,用来连接任何数据库。我们将重点放在C语言编写的嵌入式SQL程序。l 在本章中,我们将会碰到两种数据库系统的差别,即 oracle 和 db2 udb 第2页,共29页,编辑于2022年,星期六5.1 C语言中嵌入语言中嵌入SQL的介绍的介绍l关键词 exec sql声明
2、SQL语句嵌入到宿主语言源文件中。l 例如:exec sql select count(*)into:host_varl from customers;l注:1、exec sql可以扩展到该文件的多行。l 2、在嵌入式SQL中使用宿主变量时必须l 加(:)l 例:假如字符串变量cust_id在C程序中被赋值l 为“c001”第3页,共29页,编辑于2022年,星期六lexec sql select cname,discnt l into:cust_name,:cust_discntl from customers where cid=:cust_idl则检索到顾客编号为c001的顾客的名字和折
3、扣率,并将它们分别赋值给变量cust_name,l cust_discnt。l 当然,要在嵌入式SQL中使用这些宿主变量,必须先声明它们,包括对预编译程序的声明。第4页,共29页,编辑于2022年,星期六l exec sql begin declare section;l char cust_id5=“c001”;l char cust_name14;l float cust_discnt;l exec sql end declare section;l这三个变量的声明是标准的C语言中的声明,出现在begin declare 和 end declare语句之间,这是预编译程序和C语言程序都能理
4、解的相同的格式。嵌入式SQL中使用的宿主变量必须能被数据库系统识别。第5页,共29页,编辑于2022年,星期六l 在在SQL中建立和释放数据库连接:中建立和释放数据库连接:l 考虑怎样与数据库管理系统建立数据库连接。l 在Full SQL-99中 连接到SQL数据库的语法:l exec sql connect to target-server l as connect-nameuser usernamel或 exec sql connect to defaultltarget-server是目标数据库名,connect-name是对这次该数据库连接的一个名字,以后当再次使用是,可以直接引用它;
5、username是该数据库的一个合法用户名。connect to default是默认数据库的连接。第6页,共29页,编辑于2022年,星期六l由于不同平台在用户识别、权限要求方面的可变性,connect语句并不是Entry SQL-92和Core SQL-99的一部分。l 在ORACLE和DB2 UDB中,字符串常量通常不能直接作为connect语句的参数,我们需要首先声明:exec sql begin declare section;l char user_name10,user_pwd10;l exec sql end declare section;l设口令“1234”,我们对上述变量
6、初始化:l strcpy(user_name,”cap”);l strcpy(user_pwd,”1234”);第7页,共29页,编辑于2022年,星期六l那么在DB2 中嵌入式SQL的Connect语句为:exec sql connect to cap:user_name using:user_pwd;在ORACLE中嵌入式SQL的Connect语句为:exec sql connect:user_name identified by:user_pwd;简单的断开连接:exec sql disconnect current /connect_name;注意:注意:在断开连接之前,必须对成功的事
7、务提交确认,或是对失败的事务回滚以撤消已做的工作,否则直接断开连接会失败。第8页,共29页,编辑于2022年,星期六l对成功的任务结束为:lexec sql commit work;l exec sql disconnect current;l对 失败的任务结束则为:l exec sql rollback work;l exec sql disconnect current;l在ORACLE中 可以使用l exec sql commit release;l 或 exec sql rollback release;第9页,共29页,编辑于2022年,星期六l例5.1.1 实现一个嵌入式SQL程序
8、,要求程序不断提示用户输入一个顾客的cid,显示该顾客的名字和折扣,当用户输入一个空字符串则程序终止。l 程序头如下:l#include l#include”prompt.h”l/*header for dbs sqlca structure*/l exec sql include sqlca;l char cid_prompt=“please enter customer id”;第10页,共29页,编辑于2022年,星期六l程序主体代码:l int main()l exec sql begin declare section;l char cust_id5,cust_name14;l fl
9、oat cust_discnt;l char user_name20,user_pwd20;l exec sql end declare section;l exec sql whenever sqlerror goto report_error;l exec sql whenever not found goto notfound;l strcpy(user_name,”cap”);l strcpy(user_pwd,”1234”);l exec sql connect:user_name identified by:user_pwd;第11页,共29页,编辑于2022年,星期六 while
10、(prompt(cid_prompt,1,cust_id,4)=0)exec sql select cname,discnt into:cust_name,l :cust_discnt from customers where cid=:cust_id;l exec sql commit work;l printf(“customers name is%s and discnt is%5.1f”,l cust_name,cust_discnt);l continue;lnotfound:printf(“cant find%s“,cust_id)exec sql commit release;r
11、eturn 0;report_error:print_dberror();exec sql rollback release;return 1;第12页,共29页,编辑于2022年,星期六l程序说明:l print_dberror()函数显示数据库系统的错误消息,l如ORACLE中的“ORA-00942:table or view does not exist”。l prompt函数提示用户交互,prompt函数也可以接受用户输入的多个标记,若用户在提示行上键入回车,则返回结果小于0。l C语言编译程序不能识别嵌入式exec sql语句的语法,所以源程序必须先通过预编译程序将其转换成C中的正确
12、语句。(参见附录B.3)lWhenever语句是条件处理语句,该语句使我们在遇到出错和其他情况时,控制程序的运行。第13页,共29页,编辑于2022年,星期六l其格式如下:l exec sql whenever condition action;l例 exec sql whenever sqlerror goto report_error;lWhenever设置了一个条件陷阱,这样会对所有后面由exec sql语句引起的对数据库系统的调用自动检查是否出错条件,若存在这样的出错条件,就必须采取规定的动作。l(1)条件 sqlerror 这些错误通常是由编程错误引起的。l并且错误代码依赖于某一特定
13、的DBMS。lnot found 执行某条SQL语句,如 insert、delete、update等,检测是否没有记录受到该SQL语句的影响。第14页,共29页,编辑于2022年,星期六lsqlwarning 检测不是错误但应该引起注意的条件。注意:sqlwarning不是Full SQL-92的标准。l(2)动作l continue 不采取任何动作,程序按正常流程l goto 标号标号 等同与C语言中的“goto标号”l stop 结束程序的运行,撤消当前的事务,断开与 l 数据库的连接l do函数函数(ORACLE)、call函数函数(INFORMIX)引发一个对已经命名的C函数的调用,这
14、一函数返回后,程序从引发该变迁的exec sql语句之后继续执行下去。l 第15页,共29页,编辑于2022年,星期六l注意:当遇到一条后续的whenever语句覆盖了前面的whenever语句时,程序动作就被改变了。l例5.2.1l main()l exec sql whenever sqlerror stop;exec sql delete*from agents where aid=a03l goto s1;l exec sql whenever sqlerror continue;l s1:exec sql update agents set percent=percent+1;l .
15、l第16页,共29页,编辑于2022年,星期六l注意:在没有whenever时,缺省动作是continue;l可以通过 exec sql whenever sqlerror continue来重建这一缺省动作。l我们在使用whenever语句时要注意避免无限循环。l例:exec sql whenever sqlerror goto handle_error;l exec sql create table customers(cid);l 由于某个错误(磁盘空间不够等)导致建表失败,控制流转入 handle_errorl handle_error:有问题吗?有问题吗?l exec sql dro
16、p customers;l exec sql disconnect;l return 1;第17页,共29页,编辑于2022年,星期六l删除表时,可能会引起无限循环。故应改为:l handle_error:l exec sql whenever sqlerror continue;l exec sql drop customers;l exec sql disconnect;l return 1;第18页,共29页,编辑于2022年,星期六lSQL通信区:SQLCAl SQL通信区,称为SQLCA,是一个已经被声明过的内存结构(C中的结构),它的成员变量用来在数据库系统监视器与程序之间进行信息
17、通信。lSQLCA在嵌入式的C程序中声明,通常写在其他的外部声明语句前面。l exec sql include sqlca;l实际上,whenever机制的基础是一个提供了更多与条件有关的信息的错误编码系统。l 支持SQLCA的产品要填写sqlca.sqlcode(一个与错误码相关的变量)第19页,共29页,编辑于2022年,星期六l注意:SQL-92、SQL-99等标准支持一种新的报告错误的方法,SQLSTATE。在ORACLE中,必须预处理程序运行时设置 MODE=ANSI 才能支持。在DB2 UDB中提供SQLSTATE作为SQLCA的一个成员。SQLSTATE是由一个5个字符的字符串编
18、码组成,前两个字符为“类别编码”,后3个字符为“子类编码”。例如:“00000”代表没有错误,“82100”表示“内存溢出”,对于所有的产品这一编码都是相同的。若whenever语句中采取的动作不是continue,那么要进行显示的错误检测是不行的。第20页,共29页,编辑于2022年,星期六l例5.2.3 考虑如下代码段:l exec sql whenever sqlerror goto handle_error;l l exec sql create table custsl (cid char(4)not null,cname varchar(13),.);l if(strcmp(sql
19、ca.sqlstate,”82100”)=0)l l注意:虽然预处理程序在create table之后立即设置了sqlerror检测,但是该错误渐次将永远不会执行。为什么?为什么?如何修改?如何修改?第21页,共29页,编辑于2022年,星期六l exec sql whenever sqlerror goto handle_error;l.l exec sql whenever sqlerror continue;l exec sql create table custsl (cid char(4)not null,cname varchar(13).);l if(strcmp(sqlca.s
20、qlstate,”82100”)=0)l l else if(strcmp(sqlca.sqlsqlstate,”00000”)!=0)l goto handle_error;l exec sql whenever sqlerror goto handle_error;l 第22页,共29页,编辑于2022年,星期六l使用游标选择多行使用游标选择多行l 只有当select语句保证每次最多读一行到一个列变量的集合时,才能使用例5.1.1中的嵌入式select语句格式。我们在程序中如何对检索到的多行进行处理呢?l 一次一行原则一次一行原则 l 从一条select语句中,我们总是每次查看一行,每次从
21、记录集中检索一行,需要一个游标记录当前位置。第23页,共29页,编辑于2022年,星期六l例如,对一个用户交互提供的一个特定的顾客的编号cust_id,我们需要检索出为该顾客提供定货的代理商aid,以及每个代理商所提供给顾客的定单金额总值。l Exec sql select aid,sum(dollars)from orders where cid=:cust_id group by aid 下面,我们为这段select语句声明一个名为agent_dollars 的游标。Exec sql declare agent_dollars cursor for select aid,sum(dolla
22、rs)from orders where cid=:cust_id group by aid 第24页,共29页,编辑于2022年,星期六l注意:在游标被声明后,它仍然不是active状态。l 之后,必须激活该游标:l exec sql open agent_dollars;执行程序在碰到该激活语句,向数据库系统检测器发出一个调用,以执行该游标声明的select语句,将查询的结果集保存在数据库系统为该游标创建的系统缓冲区中。然后,我们可以使用fetch语句从该缓冲区中检索 连续的记录行:exec sql fetch agent_dollars into:agent_id,:dollar_sum
23、第25页,共29页,编辑于2022年,星期六l当一个游标所有的fetch语句都执行之后,应该执行close cursor语句,关闭游标,释放资源。l注:游标中保持一个当前指针,该指针总是指向最近刚刚被检索到的行,在随后的提取调用中,游标的位置指针首先加1,然后这条记录中的值被检索到指定的宿主变量中去。例5.1.2 下面给出了一个检索多行的程序:group by select语句列出了代理商的ID值,以及由这些代理商提供给某一用户指出的顾客的定单金额总值。注:该程序是按照DB2 UDB的格式第26页,共29页,编辑于2022年,星期六l#incluedl.l exec sql include s
24、qlca;l exec sql begin declare section;l char cust_id5,agent_id4;l double dollar_sum;l exec sql end declare section;int main()char cid_prompt=“please enter customer id”;exec sql declare agent_dollars cursor for select aid,sum(dollars)from orders where cid=:cust_id group by aid;第27页,共29页,编辑于2022年,星期六l
25、 exec sql whenever sqlerror goto report_error;l exec sql connect to testdb;l exec sql whenever not found goto finish;l while(prompt(cid_prompt,1,cust_id,4)=0)l exec sql open agent_dollars;l while(true)l exec sql fetch agent_dollars into l :agent_id,:dollar_sum;l printf(“%s%11.2f n”,agent_id,dollar_s
26、um);l l finish:exec sql close agent_dollars;l exec sql commit work;l 第28页,共29页,编辑于2022年,星期六l exec sql disconnect current;l return 0;lreport_error:l print_dberror();l exec sql rollback work;l exec sql disconnect current;l return 1;l l注:当查询依赖于一些宿主变量(本例注:当查询依赖于一些宿主变量(本例cust_id)时,再这些宿主变量被赋值后,以后改变宿主变时,再这些宿主变量被赋值后,以后改变宿主变量的值,对检索的列行无影响,除非,关闭游标量的值,对检索的列行无影响,除非,关闭游标后,重新打开。后,重新打开。第29页,共29页,编辑于2022年,星期六