编程 Flashcards
应用系统中使用SQL编程来访问和管理数据库中数据的方式主要有
嵌入式SQL(ESQL)、PL/SQL、ODBC编程、JDBC编程和OLEDB编程等方式。
标准SQL
是非过程化的查询语言,具有操作统一、面向集合、功能丰富、使用简单等多项优点。但和程序设计语言相比,高度非过程化的优点同时也造成了它的一个弱点:缺少流程控制的能力,难以实现应用业务中的逻辑控制。
SQL编程技术可以有效克服SQL语言实现复杂应用方面的不足,提高应用系统和RDBMS间的互操作性。
SQL的特点之一
在交互式和嵌入式两种不同的使用方式下,SQL的语法结构基本是一致的。
在程序设计的环境下,SQL语句要做某些必要的扩充。
嵌入式SQL
将SQL语句嵌入程序设计语言中。
宿主语言(简称主语言)
被嵌入的程序设计语言,如C、C++、Java。
预编译
对ESQL,RDBMS一般采用预编译方法处理,即由RDBMS的预处理程序对源程序进行扫描,识别出ESQL语句,把它们转换成主语言调用语句,以使主语言编译程序能识别它们,然后由主语言的编译程序将纯的主语言程序编译成目标码。
区分SQL语句与主语言语句
在ESQL中,为了能够区分SQL语句与主语言语句,所有SQL语句都必须加前缀EXEC SQL,以(;)结束成为一个程序片段:
EXEC SQL ;
将SQL嵌入到高级语言中混合编程
SQL语句负责操纵数据库,存取数据库中的数据。高级语言语句(主语言语句)负责控制程序流程以及对取出的数据做进一步加工处理。
数据库工作单元与源程序工作单元之间的通信
1。向主语言传递SQL语句的执行状态信息,使主语言能够据此信息控制程序流程,主要用SQL通信区(SQLCA)实现。
2。主语言向SQL语句提供参数,主要用主变量实现。
3。将SQL语句查询数据库的结果交主语言处理,主要用主变量和游标实现。
SQL通信区
SQL语句执行后,系统要反馈给应用程序若干信息,主要包括描述系统当前工作状态和运行环境的各种数据。这些信息将送到SQLCA中。应用程序从SQLCA中取出这些状态信息,据此决定接下来执行的语句。
SQLCA在应用程序中用EXEC SQL INCLUDE SQLCA加以定义。SQLCA中有一个变量SQLCODE,用来存放每次执行SQL语句后返回的代码。
应用程序每执行完一条SQL语句之后都应该测试一下SQLCODE的值,以了解该SQL语句执行情况并做相应处理。如果SQLCODE等于预定义的常量SUCCEED,则表示SQL语句成功,否则在SQLCODE存放错误代码。程序员可以根据错误代码查找问题。
主变量
嵌入式SQL语句中可以使用主语言的程序变量来输入或输出数据。
一个主变量可以附带一个任选的指示变量。
所有主变量和指示变量必须在SQL语句BEGIN DECLARE SECTION与END DECLARE SECTION之间进行说明。说明之后,主变量可以在SQL语句中任何一个能够使用表达式的地方出现,为了与数据库对象名(表名、视图名、列名等)区别,SQL语句中的主变量名和指示变量前要加冒号(:)作为标志。
主变量的定义
SQL语句中可以使用主语言的程序变量简称为主变量。
主变量根据其作用的不同,分为
输入主变量和输出主变量。
输入主变量由应用程序对其赋值,SQL语句引用;输出主变量由SQL语句对其赋值或设置状态信息,返回给应用程序。
指示变量
是一个整型变量,用来"指示"所指主变量的值或条件。
指示变量可以指示输入主变量是否为空值,可以检测输出主变量是否为空值,值是否被截断。
游标
SQL是面向集合的,一条SQL语句可以产生或处理多条记录。而主语言是面向记录的,一组主变量一次只能存放一条记录。所以仅使用主变量并不能完全满足SQL语句向应用程序输出数据的要求,为此嵌入式SQL引入了游标的概念,用游标来协调这两种不同的处理方式。
游标是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果,每个游标区都有一个名字。用户可以通过游标逐一获取记录,并赋值给主变量,交由主语言进一步处理。
建立和关闭数据库连接
嵌入式SQL程序要访问数据库必须先连接数据库。RDBMS根据用户信息对连接请求进行合法性验证,只有通过了身份验证,才能建立一个可用的合法连接。
建立连接的ESQL语句
EXEC SQL CONNECT TO target [AS connection-name] [USER user-name];
target是要连接的数据库服务器,它可以是一个常见的服务器标识串,如@:。或者是包含服务器标识的SQL串常量,也可以是DEFAULT。
connection-name是可选的连接名,连接必须是一个有效的标识符,主要用来识别一个程序内同时建立的多个连接,如果在整个程序内只有一个连接也可以不指定连接名。
如果程序运行过程中建立了多个连接,执行的所有数据库单元的工作都在该操作提交时所选择的当前连接上。程序运行过程中可以修改当前连接,对应的嵌入式SQL语句为
EXEC SQL CONNECTION connection-name|DEFAULT;
关闭数据库连接
当某个连接上的所有数据库操作完成后,应用程序应该主动释放所占用的连接资源。关闭数据库连接的ESQL语句是
EXEC SQL DISCONNECT [connection-name];
其中connection-name是EXEC SQL CONNECT所建立的数据库连接。
不用游标的SQL语句
有的ESQL SQL语句不需要使用游标。它们是:说明性语句、数据定义语句、数据控制语句、查询结果为单记录的SELECT语句、非CURRENT形式的增删改语句。
查询结果为单记录的SELECT语句
因为查询结果只有一个,只需要用INTO子句指定存放查询结果的主变量。
使用单记录的SELECT语句需要注意
1。INTO子句、WHERE子句和HAVING短语的条件表达式中均可以使用主变量。
2。查询结果为空值的处理。
查询返回的记录中,可能某些列为空值NULL。为了表示空值,在INTO子句的主变量后面跟有指示变量,当查询得出的某个数据项为空值时,系统会自动将相应主变量后面的指示变量置为负值,而不再向该主变量赋值。所以当指示变量为负值时,不管主变量为何值,均认为主变量值为NULL。
指示变量只能用于INTO子句中。
3。如果查询结果实际上并不是单条记录,而是多条记录,则程序出错,RDBMS会在SQLCA中返回错误信息。
非CURRENT形式的增删改语句
有些增删改语句不需要使用游标,不是CURRENT形式的。在UPDATE的SET子句和WHERE子句中可以使用主变量,SET子句还可以使用指示变量。
必须使用游标的SQL语句
查询结果为多条记录的SELECT语句、CURRENT形式的UPDATE和DELETE语句。
查询结果为多条记录的SELECT语句
一般情况下,SELECT语句查询结果是多条记录,因此需要用游标机制,将多条记录一次一条送主程序处理,从而把对集合的操作转换为对单个记录的处理。
使用游标的步骤为:
1。说明游标。用DECLARE语句为一条SELECT语句定义游标:
EXEC SQL DECLARE CURSOR FOR ;
定义游标仅仅是一条说明性语句,这时RDBMS并不执行SELECT语句。
2。打开游标。用OPEN语句将定义的游标打开。
EXEC SQL OPEN ;
打开游标实际上是执行相应的SELECT语句,把查询结果取到缓冲区中。这时游标处于活动状态,指针指向查询结果集中的第一条记录。
3。推进游标指针并取当前记录。
EXEC SQL FETCH INTO [] [, []]…;
其中主变量必须与SELECT语句中的目标列表达式具有一一对应关系。
用FETCH语句把游标指针向前推进一条记录,同时将缓冲区中的当前记录取出来送至主变量供主语言进一步处理。通过循环执行FETCH语句逐条取出结果集中的行进行处理。
4。关闭游标。用CLOSE语句关闭游标,释放结果集占用的缓冲区及其他资源。
EXEC SQL CLOSE ;
游标被关闭后,就不再和原来的查询结果集相联系。但被关闭的游标可以再次被打开,与新的结果集相联系。
CURRENT形式的UPDATE和DELETE语句
UPDATE语句和DELETE语句都是集合操作,如果只想修改或删除其中某个记录,则需要用带游标的SELECT语句查出所有满足条件的记录,从中进一步找出要修改或删除的记录,然后用CURRENT形式的UPDATE语句和DELETE语句修改或删除之。即UPDATE语句和DELETE语句中要用子句WHERE CUURENT OF 来表示修改或删除的是最近一次取出的记录,即游标指针指向的记录。
当游标定义中的SELECT语句带有UNION或ORDER BY子句时,或者该SELECT语句相当于定义了一个不可更新的视图时,不能用CURRENT形式的UPDATE语句和DELETE语句。
静态SQL语句
前面所讲的嵌入式SQL语句中使用的主变量、查询目标列、条件等都是固定的,属于静态SQL语句。
动态SQL
静态嵌入式SQL语句能够满足一般要求,但某些应用可能要到执行时才能够确定要提交的SQL语句,查询的条件。就要使用动态SQL来解决这类问题。
动态SQL方法允许在程序运行过程中临时"组装"SQL语句。动态SQL支持动态组装SQL语句和动态参数两种形式,给开发者提供设计任意SQL语句的能力。
使用SQL语句主变量
程序主变量包含的内容是SQL语句的内容,而不是原来保存数据的输入或输出变量,这样的变量成为SQL语句主变量。SQL语句主变量在程序执行期间可以设定不同的SQL语句,然后立即执行。
(const char *stmt=”CREATE TABLE test(a int);”;
EXEC SQL EXECUTE IMMEDIATE :stmt;)