第15章 嵌入式SQL的应用

SQL在如今的数据库领域虽然应用的非常的广泛,但是,与一些高级语言相比,在某些功能上还有一定的限制。也就是说,在有些功能上,纯粹使用SQL语句还无法实现。数据库访问只是其中一个部件。有些如与用户交互、图形化显示数据等动作只能通过应用高级语言来实现。

15.1 嵌入式SQL介绍
在关系数据库中,可以将SQL语句嵌入到宿主语言中,既实现嵌入式SQL,从而完成在单独使用SQL语句时难以实现的功能。

15.1.1 直接调用SQL
直接调用SQL也称为交互式SQL。通常是指用户在数据库产品提供的客户端应用软件中直接运行SQL语句,同时通过该软件返回SQL语句的执行结果。前面所讲解的SQL Server数据库及其相关的示例,其交互式SQL的实现都是通过在查询分析器中实现的。在SQL Server的查询分析器中直接运行SQL语句,同时返回语句的执行结果,如图15.1所示。

图15.1 SQL Server2005的查询分析器界面

说明:本书中所使用的SQL Server数据库是SQL Server2005的SQL Server Management
Studio版本,该版本将SQL Server2000中的企业管理器和查询分析器的功能都集合在一起,图19.1就是该版本的查询分析器界面。

在不同的数据库管理系统当中,实现交互式SQL的方法是不同的。在Oracle数据库当中,通过SQL*Plus软件实现交互式SQL。但是,无论通过什么方式实现交互式SQL,SQL中其基本的SELECT、INSERT、UPDATE和DELETE语句以及与存储过程、触发器、事务和连接等有关的语句,几乎都可以在交互式SQL环境中实现,即实现直接调用操作。

交互式SQL是一个纯SQL环境,因此,通过交互式SQL很难与应用程序建立起连接,这就使得交互式SQL的应用受到了很大的限制。在实际应用中,大多数的访问都是通过嵌入式SQL和SQL调用层接口(CLI)完成的,很少依靠交互式SQL来实现。

15.1.2 SQL调用层接口(CLI)
通常情况下,应用程序要想与SQL数据库之间进行交流,需要SQL调用层接口来实现。SQL调用层接口是一种支持预定义例程的应用程序接口。应用程序调用例程,然后连接到数据库。通过例程可以访问数据库中的数据信息,同时将访问到的数据信息返回给应用程序。
应用程序与SQL数据库之间通过SQL调用层接口(CLI)进行交流的过程如图15.2所示。

图15.2 通过SQL调用层接口(CLI)访问数据库的流程

通常情况下,应用程序与CLI例程之间是通过函数来实现的。
程序通过使用函数来调用CLI例程,函数通过设定参数把值传递给例程,由函数作为应用程序和SQL数据库之间的接口。目前应用最广泛的的CLI模块工具是Microsoft公司的ODBC(Open Database Conectivity)和Microsoft公司的OLE-DB/ADO(ActiveX Data Object)。
1.ODBC
ODBC技术是对数据库进行访问的标准应用程序接口(API)和Windows开放式服务体系结构OSA的一个重要组成部分,已被得到了广泛的应用。
ODBC为开发应用数据库程序提供了非常强大的功能和灵活性。ODBC通过驱动程序管理器与数据库进行交换信息。驱动程序管理器负责将应用程序对ODBC的调用,传递给正确的驱动程序,而驱动程序在执行完相应的操作后,将结果通过驱动程序管理器返回给应用程序。
ODBC所包含的部件及其关系如图15.3所示。

图15.3 ODBC包含的各部件及其关系图

说明:应用程序要访问一个数据库,首先必须用ODBC管理器注册一个数据源,管理器根据数据源提供的数据库位置、数据库类型及ODBC驱动程序等信息,建立起ODBC与具体数据库的联系。

2.OLE-DB/ADO
OLE DB是系统级的编程接口,可在C/C++语言中直接使用。OLE DB提供了一组标准的服务组件,用于提供查询、缓存、数据更新和事务处理等操作。OLE DB还通过定义的COM接口将各种数据系统的访问操作进行封装,为数据使用方和数据提供方建立了标准。
微软公司的ADO是最新的对象层次上的数据操作技术,ADO技术为操作OLE DB数据源提供了一套高层次自动化接口。虽然OLE DB已经是一个强大的数据操作接口,但是很多的数据库应用程序开发人员并不需要OLE DB提供的操作数据的底层控制接口。

注意:通过CLI访问SQL数据库的核心并不在于SQL本身,而在于访问SQL数据库的高级语言开发工具(如C语言)以及CLI实现的本身。

ADO同OLE DB、数据库应用以及数据源之间的关系如图15.4所示。

图15.4 ADO同OLE DB、数据库应用以及数据源之间的关系

15.2 嵌入式SQL的使用
15.2.1 嵌入式SQL
嵌入式SQL是指将SQL语言嵌入到某种高级语言当中,如在FORTRAN、COBOL和C语言中都可以嵌入SQL语言,来弥补SQL语言在实现复杂应用方面的不足。
通常使用预处理的方式来实现嵌入式SQL。通过扩充宿主语言(高级编程语言)的编译程序,使其能够处理SQL语句和预处理的方式。预处理方式的处理过程主要可以表示为以下几个方面:

  • 由DBMS的预处理程序扫描源程序,从源程序中识别出SQL语句使其能够被编译执行。
  • 把识别出的SQL语句转换成主语言调用语句,使高级语言编译程序能识别该调用语句。
  • 由高级语言的编译程序将整个源程序编译成目标代码。

其具体实现的流程如图15.5所示。

图15.5 嵌入式SQL预处理方式的实现

从图15.5中可以看出,预处理方式首先从含有高级语言和SQL语句的程序开始。在编译程序之前,首先把程序提交给一个预编辑器,通过预编译器将SQL语句从高级语言中分离出来,并且实现对SQL语句的调用。然后通过高级语言编译器按照自己的方式进行编译,最后得到目标代码,实现连接到数据库的例程当中。

15.2.2 SQL通信区
SQL通信区(SQL Communication Area)简称SQLCA。在SQL语句运行时,DBMS返回描述系统当前工作状态以及运行环境状态等信息。应用程序根据从SQLCA中取出的信息来决定下一步要执行的操作。
在使用SQLCA时,首先需要在高级语言中定义,其实现定义的语句结构如下所示:
EXEC SQL INCLUDE SQLCA
SQLCA中包含的主要字段及其字段的含义如下所示:

  • SQLCAID:该字段含有8字节字符,其作用是在查看内存内容时帮助进行调试。
  • SQLCABC:该字段是包含SQLCA结构长度的长整型数。
  • SQLCODE:数据库在请求上检测到错误时,指定错误代码的长整数。成功操作的错误代码是0,正数表示警告,负数表示错误。
  • SQLERRML:字段中信息的长度。
  • SQLERRMC:要插入到错误消息中的零个或多个字符串。
  • SQLERRD:长整数的实用程序数组。

下面通过一个示例来说明如何在嵌入式SQL语句中应用SQLCA。
【上机实战】
在C语言中嵌入SQL语句中SQLCA。

#include<stdio.h>
/* 定义SQLCA变量,用于进行错误检测 */
EXEC SQL INCLUDE SQLCA;
main()
{/* 连接数据库 */EXEC DQL CONNECT TO MyDataBase USER SA;if(sqlca.sqlcode){printf(Printer,"连接数据库服务器错误!");exit();}
}

示例中的代码表示通过SQLCA检测在连接数据库时是否有错误产生。如果sqlca.sqlcode的值为0,则连接数据库的SQL语句执行失败,说明连接数据库不成功,程序将提示“连接数据库服务器错误!”的提示信息。

15.2.3 主变量
在SQL语句中使用的高级语言程序的变量简称为主变量。使用主变量可以输入或输出数据。
1.主变量的分类
主变量可以分为输入主变量和输出主变量两种。输入主变量通过SQL语句进行引用,然后由应用程序对其赋值;输出主变量由SQL语句对该变量进行赋值或设置状态信息,然后将该信息返回给应用程序。
利用输入主变量,可以指定向数据库中插入的数据,将数据库中的数据修改为指定值的功能。利用输出主变量,可以得到SQL语句的结果数据和状态。
2.主变量的定义和使用
在SQL语句中,输入主变量前面要加冒号,以便于区别数据库对象名。输入主变量可以被应用在SQL的数据操纵语句当中的任何位置。定义输出变量的方法是在SQL语句的BEGIN DECLARE SECTION与END DECLARE SECTION之间进行说明。
下面通过一个示例来讲解如何定义输入主变量。
【上机实战】
定义输入主变量。

/* 定义输入主变量 */
EXEC SQL SELECT sName,sSex,sPhone,sAddress/* 下面的变量tName,tSex,tPhone,tAddress,In_No是在高级语言中定义的 */INTO :tName,:tSex,:tPhone,:tAddressFROM employeeWHERE No=:In_No;

下面通过一个示例来讲解如何定义输出主变量。

/* 定义输出主变量 */
EXEC SQL BEGIN DECLARE SECTIONINT out_No;CHAR out_name[10];CHAR out_sex[2];INT out_age;CHAR out_phone[11];CHAR out_address[50];CHAR SQLSTATE[6]
EXEC SQL END DECLARE SECTION
EXEC SQL SELECT sName,sSex,sAge,sPhone,sAddressINTO :tName,:tSex,:tAge,:tPhone,:tAddressFROM employeeWHERE No=:In_No;

15.2.4 在嵌入式SQL中使用SQL语句
本节中讲解的是在嵌入式SQL中如何使用SELECT语句、UPDATE语句、DELETE语句和INSERT语句。

1.在嵌入式SQL中使用SELECT语句
在嵌入式SQL中使用SELECT语句是对交互式SELECT语句的补充。嵌入式SQL中使用了INTO语句,并且其返回的结果只有一条记录。
下面通过一个示例来说明如何在嵌入式SQL中使用查询结果为单记录的SELECT语句。
【上机实战】
从员工信息表(employee)中查询员工编号(No)为1001的员工姓名和性别信息,并且将其值赋予主变量

tName和tSex。
EXEC SQL SELECT sName,Sex
INTO :tName,:tSex
FROM employee
WHERE No=1001

代码中的tName和tSex都是前面示例中定义过的主变量。语句返回员工信息表(employee)中员工编号为1001的单行记录信息。

2.在嵌入式SQL中使用UPDATE语句
在嵌入式SQL中使用UPDATE语句的语法形式与使用交互式UPDATE语句的语法形式基本相似。只不过在嵌入式SQL中使用的UPDATE语句中的SET子句和WHERE子句中可以使用主变量而以。
下面通过一个示例来说明如何在嵌入式SQL中使用UPDATE语句。
【上机实战】
通过主变量将员工工资表(EmPays)中所有女员工的工资提高。假设增加的工资已经赋给主变量

AddPays。
EXEC SQL UPDATE EmPays
SET EmPays=EmPays + :AddPays
WHERE EmSex='女'

该代码执行以后,员工工资表(EmPays)中所有女员工的工资提都被更改提高。
3.在嵌入式SQL中使用DELETE语句
在嵌入式SQL中使用DELETE的语法结构中,除了在其WHERE子句中可以使用主变量之外,其他部分都与交互式DELETE语句相同。
下面通过一个示例来说明如何在嵌入式SQL中使用DELETE语句。
【上机实战】
通过主变量将学生信息表(student)中所有年龄大于某值的员工信息删除。假设该值已经赋予了主变量

del_age。
EXEC SQL DELETE
FROM student
WHERE SAge>:del_age;

该代码执行以后,学生信息表(student)中所有年龄大于主变量del_age中值的员工信息都被删除。
4.在嵌入式SQL中使用INSERT语句
在嵌入式SQL中使用INSERT的语法结构中,除了在其VALUES子句中可以使用主变量之外,其他部分都与交互式INSERT语句相同。
下面通过一个示例来说明如何在嵌入式SQL中使用INSERT语句。
【上机实战】
通过主变量向学生信息表(student)中插入数据信息,并且假定表中的各字段信息都存储在主变量stud_no、stud_spno、stud_name和stud_age当中。

EXEC SQL INSERT INTO student
VALUES(:stud_no,:stud_spno,:stud_name,:stud_age);

该代码执行以后,主变量中的数据信息被插入到学生信息表(student)当中。

15.2.5 在嵌入式SQL中使用游标
嵌入式SQL中的一组主变量一次只能存放一条记录。因此,只是使用主变量,并不能完全满足SQL语句向应用程序输出数据的要求。为此,嵌入式SQL引入了游标的概念,用游标来解决上述出现的问题。
在嵌入式SQL中,游标是系统为用户开设的一个数据缓冲区,其用于存放SQL语句的执行结果。用户可以用SQL语句逐一从游标中获取记录,并赋给主变量,然后再通过高级语言程序进行处理,完成相应的操作。
在嵌入式SQL中使用游标主要有以下几个步骤:
(1)定义一个游标,使之对应一个SELECT语句。实现过程可用下面的语句进行表示:

EXEC SQL DECLARE <游标名称> CURSOR FOR <SELECT语句>

(2)打开游标,在定义了游标之后,可以执行游标对应的查询,其结果集合为该游标的活动集。实现过程可用下面的语句进行表示:

EXEC SQL OPEN <游标名称>

此时游标指针定位于结果集中第一行的前一行。
(3)在活动集中将游标移到特定的行,并取出该行数据放到相应的主变量中,其实现的过程可以用下面的语句进行表示:

EXEC SQL FETCH FROM <游标名称> INTO <主变量名称>

(4)关闭游标,游标在使用完成以后,需要释放活动集及其所占用的资源,使它不再和查询结果相联系。其实现的过程可以通过下面的语句进行表示:

EXEC SQL CLOSE <游标名称>

下面通过一个具体的示例来说明如何在嵌入式SQL中使用游标。
【上机实战】
在C语言中使用嵌入式SQL,并且使用了游标。

EXEC SQL INCLUDE SQLCA;
EXEC SQL BEGIN DECLARE SECTION;
CHAR employee_name[10];
CHAR employee_phone[11];
CHAR emoloyee_address[50];
EXEC SQL END DECLARE SECTION;
main()
{EXEC SQL DECLARE employee_Cursor CURSOR FORSELECT sName,sPhone,sAddress;/* 打开游标*/EXEC SQL OPEN employee_Cursor;for(;;){/* 将当前值当道主变量当中*/EXEC SQL FETCH employee_Cursor INTO :employee_name,:employee_phone,:emoloyee_address;if(sqlca.sqlcode<>0)break;/* 输出结果*/printf("姓名:%s,联系电话:%s,联系地址:%s",employee_name,employee_phone,emoloyee_address);}/* 关闭游标*/
EXEC SQL CLOSE employee_Cursor
}

上面示例演示的是在嵌入式SQL中游标最基本的使用方法。下面讲解如何在查询结果为多条记录的SELECT语句中使用游标。
下面的代码演示的是,通过主变量从员工工资表(EmPays)中检索员工姓名(EmName)、员工性别(EmSex)和员工的基本工资(EmBasicPays)信息,其中员工姓名由主变量InName给出。

Void Pays()
{EXEC SQL INCLUDE SQLCA;EXEC SQL BEGIN DECLARE SECTION;CHAR emname[10];CHAR emsex[2];INT empays;
EXEC SQL END DECLARE SECTION;
gets(emname);
EXEC SQL DECLARE emppay_cursor CURSOR FOR
SELECT EmName,EmSex,EmBasicPays
FOR EmPays
WHERE EmName=:emname;
EXEC SQL OPEN emppay_cursor;
WHILE(1)
{EXEC SQL FETCH FROM emppay_cursor INTO :emname,:emsex,:empays;if(sqlca.sqlcode<>0)break;printf("姓名:%s,性别:%s,基本工资:%d",emname,emsex,empays);
}
EXEC SQL CLOSE emppay_cursor;
}

第15章 嵌入式SQL的应用相关推荐

  1. 第十二章 使用嵌入式SQL(三)

    文章目录 第十二章 使用嵌入式SQL(三) 主机变量 主机变量示例 用列号下标的主机变量 `NULL`和未定义的主机变量 主机变量的有效性 主机变量和程序块 第十二章 使用嵌入式SQL(三) 主机变量 ...

  2. 《SQL必知必会》读书笔记上(第1~15章)

    目录 第1章 了解SQL 第2章 MySQL简介 第3章 使用MySQL 3.1 连接数据库 3.2 选择数据库 3.3 显示数据库和表 3.4 其他SHOW语句 第4章 检索数据 4.1 SELEC ...

  3. 【梳理】数据库系统概论 第8章 数据库编程 8.1 嵌入式SQL 8.2 过程化SQL 8.3 存储过程和函数 8.4 ODBC编程

    教材:王珊 萨师煊 编著 数据库系统概论(第5版) 高等教育出版社 注:文档高清截图在后 第8章 数据库编程 标准SQL是非过程化的查询语言,操作统一.面向集合.功能丰富.使用简单.非过程化语言是相对 ...

  4. 嵌入式系统知识点总结【1-5章】

    第一章 嵌入式系统概述 1.嵌入式系统的定义及特点 定义 从广义的角度:嵌入式系统是一切非PC和大型机的计算机系统 从应用的角度:嵌入式系统是以应用为中心,以计算机技术为基础,采用可剪裁软硬件,适用于 ...

  5. DB2数据库嵌入式SQL开发

    如有转载,请注明出处:http://blog.csdn.net/embedded_sky BY:super_bert@csdn 1.1 DB2应用程序开发概述 1.1.1    程序结构 DB2应用程 ...

  6. 第15章:存储引擎和表类型#innodb的性能调整

    原贴:http://dev.mysql.com/doc/refman/5.1/zh/storage-engines.html#innodb-tuning 第15章:存储引擎和表类型 目录 15.1. ...

  7. linux cached释放_正点原子Linux第四十一章嵌入式Linux LED驱动开发实验

    1)资料下载:点击资料即可下载 2)对正点原子Linux感兴趣的同学可以加群讨论:935446741 3)关注正点原子公众号,获取最新资料更新 第四十一章嵌入式Linux LED驱动开发实验 上一章我 ...

  8. 数据库期末总结笔记(零基础)-第三章 关系数据库SQL

    第三章 关系数据库SQL 三.SQL查询 1.基本查询格式 select [distinct] (去重)所查内容 from 所查询的表(可多个)where 要求条件 例:查计算机科学系全体学生 sel ...

  9. 【正点原子Linux连载】第四十一章 嵌入式Linux LED驱动开发实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0

    1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...

最新文章

  1. Saltstack自动化环境部署
  2. Windows 11,一个新功能,一场新屠杀!
  3. xml内容过多装不下,怎么实现下滑功能(最简单的下滑功能实现)
  4. 大型网站后台架构的Web Server与缓存
  5. matlab复数方程的根,matlab解一元三次方程,得到的都是复数根。
  6. Python 爬取周杰伦instagram
  7. 前端经典面试题 不经典不要star!
  8. Android显存到内存拷贝耗时,memcpy速度太慢?掌握这个技术让内存拷贝效率成倍提升...
  9. python中while语句是_如何在Python中使用while语句[适合初学者]
  10. java 6 损坏,Java 异常处理六
  11. c语言检查tcp连接_TCP/IP的底层队列
  12. 【第二篇】ASP.NET MVC快速入门之数据注解(MVC5+EF6)
  13. Python开发过程中错误解决记录【持续更新记录,欢迎交流】
  14. linux重定向文件容加时间,[单选] linux系统,把当前日期重定向到/tmp/date文件中,并不想覆盖原来的内容,下面正确的操作是()。...
  15. 【图纸加密】命令lockdwg转换为多重属性块
  16. 非线性激活函数的作用
  17. 前沿科技赋能教育,掌门优课创新教学体验
  18. 单位强制解除与员工的劳动关系怎么办
  19. Unity获取包名,产品名,版本号等
  20. Jenkins配置远程服务器SSH Servers节点参数设置说明

热门文章

  1. 如何让简历中的“岗位业绩”打动HR?
  2. Mysql current_time,current_date()与now()区别
  3. 论文阅读笔记:Ultra-Scalable Spectral Clustering and Ensemble Clustering
  4. SQL入门经典第5版(Sams Teach Yourself SQL in 24 Hours, 5th)随书习题的建表和插入
  5. Linux中reboot和reset的使用和区别
  6. Hadoop笔记-02 安装
  7. vue 地图可视化 (2)
  8. FPGA零基础学习:半导体存储器和可编程逻辑器件简介
  9. 分析如何区分MOS管是N沟道还是P沟道-KIA MOS管
  10. 薛斯通道的十二种买入法和四种卖出法