嵌入式SQL

来源:互联网 发布:电气原理图画图软件 编辑:程序博客网 时间:2024/06/05 20:41

嵌入式SQL语言把SQL语言嵌入到某种高级语言中使用,利用高级语言的过程性结构来弥补SQL语言实现复杂应用方面的不足。这种方式下使用的SQL语言称为嵌入式SQL(Embedded SQL),而嵌入SQL的高级语言称为主语言或宿主语言。

1.1 嵌入式SQL的一般形式

    对宿主型数据库语言SQL,DBMS可采用两种方法处理,一种是预编译,另一种是修改和扩充主语言使之能处理SQL语句。目前采用较多的是预编译的方法。即由DBMS的预处理程序对源程序进行扫描,识别出SQL语句。把它们转换成主语言调用语句,以使主语言编译程序能识别它,最后由主语言的编译程序将整个源程序编译成目标码。

在嵌入式SQL中,为了能够区分SQL语句与主语言语句,所有SQL语句都必须加前缀 EXEC SQL.。SQL语句的结束标志则随主语言的不同而不同。

例如在PL/1和C中以分号(;)结束;

EXEC SQL <SQL 语句> ;

在COBOL中以END-EXEC 结束;

EXEC SQL < SQL 语句> END-EXEC

例如 一条交互形式的SQL语句:DROP TABLE Student ;

嵌入到C程序中,应写成: EXEC SQL DROP TABLE Student ;

嵌入SQL语句根据其作用的不同,可分为可执行语句说明性语句两种。可执行语句又分为数据定义数据控制数据操纵三种。

   在宿主程序中,任何允许出现可执行的高级语言语句的地方,都可以写可执行SQL语句 ;任何允许出现说明型高级语言语句的地方,都可以写说明性SQL语句。

1.2 嵌入式SQL语句与主语言之间的通信

   将SQL嵌入到高级语言中混合编程,SQL语句负责操纵数据库,高级语言语句负责控制程序流程。这时程序中会含有两种不同计算模型的语句,一种是描述性的面向集合的SQL语句,一种是过程性的高级语言语句,它们之间应该如何通信呢?

数据库工作单元与源程序工作单元之间的通信主要包括:

(1)    向主语言传递SQL语句的执行状态信息,使主语言能够据此信息控制程序流程,主要用SQL通信区(SQL Communication Area ,简称SQLCA)实现;

(2)    主语言向SQL语句提供参数,主要用主变量实现;

(3)    将SQL语句查询数据库的结果交主语言进一步处理,主要用主变量和游标(Cursor)实现。

一. SQL通信区

SQL语句执行后,系统要反馈给应用程序若干信息,主要包括描述系统当前工作状态和运行环境的各种数据。这些信息将送到SQL通信区SQLCA种。应用程序从SQLCA中取出这些状态信息,据此决定接下来执行的语句。

SQLCA是一个数据结构,在应用程序中用EXEC  SQL  INCLUDE  SQLCA 加以定义。SQLCA中有一个存放每次执行SQL语句后返回代码的变量SQLCODE.。应用程序每执行完一条SQL语句之后都应该测试一下SQLCODE的值,以了解SQL语句执行情况并作相应处理。如果SQLCODE等于预定义的常量SUCCESS,则表示SQL语句成功,否则在SQLCODE中存放错误代码。

例如,在执行删除语句DELETE后,不同的执行情况SQLCA中有下列不同的信息:

       成功删除,并有删除的行数(SQLCODE = SUCCESS)

       无条件删除警告信息

       违反数据保护规则,拒绝操作

       没有满足条件的行,一行也没有删除

       由于各种原因,执行出错

二. 主变量

    嵌入式SQL语句中可以使用主语言的程序变量来输入或输出数据。我们把SQL语句中使用的主语言程序变量简称为主变量

   主变量根据其作用的不同,分为输入主变量输出主变量输入主变量由应用程序对其赋值,SQL语句引用;输出主变量由SQL语句对其赋值或设置状态信息,返回给应用程序。一个主变量有可能既是输入主变量又是输出主变量。利用输入主变量,可以指定向数据库中插入的数据,可以将数据库中的数据修改为指定值,可以指定执行的操作,可以指定WHERE 子句或HAVING子句中的条件。利用输出主变量,可以得到SQL语句的结果数据和状态。

   所有主变量和指示变量(指示变量是一个整形变量,用来“指示“所指主变量的值或条件)必须在SQL语句BEGIN  DECLARE  SECTION  与END  DECLARE SECTION 之间进行说明。说明之后,主变量可以在SQL语句中任何一个能够使用表达式的地方出现,为了与数据库对象名(表名,视图名,列名等)区别,SQL语句中的主变量名前要加冒号(:)作为标志。同样,SQL语句中的指示变量前也必须加冒号,并且要紧跟在所指主变量之后。而在SQL语句之外,主变量和指示变量均可以直接引用,不必加冒号。

三.游标

      SQL语言与主语言具有不同的数据处理方式。SQL语言是面向集合的,一条SQL语句原则上可以产生或处理多条纪录。而主语言是面向纪录的,一组主变量一次只能存放一条纪录。所以仅使用主变量并不能完全满足SQL语句向应用程序输出数据的要求,为此嵌入式SQL引入了游标的概念,用游标来协调这两种不同的处理方式。游标是系统为用户可设的一个数据缓冲区,存放SQL语句的执行结果,每个游标区都有一个名字。用户可以通过游标逐一获取纪录。并赋给主变量,交由主语言进一步处理。

   EXEC  SQL INCLUDE   SQLCA      END-EXEC.  ……………………………定义SQL通信区

01  ORA-WORKING-ITEMS.                                          

   EXEC  SQL BEGIN     DECLARE SECTION         END-EXEC…….主变量说明开始

   05  ORA-USER                  PIC  X(01)  VALUE '/'.         

   05  TBL-WSGTMMPE.                                            

         EXEC     SQL    INCLUDE WSGTMMPE.cpy    END-EXEC.      

    05  S-WSGP83I.                                               

         EXEC     SQL    INCLUDE WSGQP83I.cpy    END-EXEC.      

    05  KEY-SEC-CODE.                                            

         10  KEY-SEC-CODE1           PIC  X(04).                    

         10  KEY-SEC-CODE2           PIC  X(01).                    

    05  KEY-SEC-CD                PIC  X(14).                    

 EXEC  SQL END       DECLARE SECTION         END-EXEC.   …..主变量说明结束

EXEC SQL  DECLARE SEL_PLACE CURSOR FOR S  END-EXEC.  游标操作(定义游标)

EXEC SQL OPEN  SEL_PLACE END-EXEC.                     游标操作 (打开游标)

EXEC SQL  FETCH  SEL_PLACE INTO ….                        游标操作  (推进游标

指针并将当前数据放入主变量)

EXEC  SQL  CLOSE  SEL_PLACE     END-EXEC.         游标操作 (关闭游标)

 

1.3 不用游标的SQL语句

  不用游标的SQL语句有:

       说明性语句

       数据定义语句

       数据控制语句

       查询结果为单纪录的SELECT语句

       非CURRENT 形式的UPDATE 语句

       非CURRENT 形式的DELETE 语句

       INSERT语句

所有的说明性语句及数据定义与控制语句都不需要使用游标。它们是嵌入式SQL中最简单的一类语句,不需要返回结果数据,也不需要使用主变量。在主语言中嵌入说明性语句及数据定义与控制语句,只要给语句加上前缀 EXEC SQL 和语句结束符即可。

  INSERT语句也不需要使用游标,但通常需要使用主变量。

SELECT语句,UPDATE语句,DELETE 语句则要复杂些。

一.        说明性语句

说明性语句是专为在嵌入SQL中说明主变量等而设置的,主要有两条语句:

EXEC  SQL  BEGIN  DECLARE  SECTION; 和

EXEC  SQL  END   DECLARE  SECTION;

两条语句必须配对出现,相当于一个括号,两条语句中间是主变量的说明

二.        数据定义语句

  例1 建立一个”学生”表Student.

      EXEC SQL CREATE TABLE Student (

                   Sno        CHAR(5) NOT NULL UNIQUE,

                   Sname     CHAR(20),

                   Ssex       CHAR(1)’

                 Sage        INT,

                 Sdept       CHAR(15));

     EXEC SQL DROP TABLE Student;

数据定义语句中不允许使用主变量。例如下列语句是错误的:

   EXEC SQL DROP TABLE :table_name;

三.        数据控制语句

   例2.把查询Student查询表权限授给用户U1.

         EXEC  SQL  GRANT  SELECT  ON  TABLE  Student TO U1;

四.        查询结果为单纪录的SELECT语句

在嵌入式SQL中,查询结果为单纪录的SELECT语句需要用INTO 子句指定查询结果的存放地点。该语句的一般格式为:

EXEC SQL SELECT [ALL|DISTINCT]<目标列表达式>[,<目标列表达式>]……….

           INTO <主变量>[<指示变量>][,<主变量>[<指示变量>]]……

           FROM <表名或视图名> [,<表名或视图名>]。。。。。。

           [WHERE <条件表达式>]

           [GROUP BY <列名 1> [HAVING<条件表达式>]]

           [ORDER BY <列名 2> [ASC|DESC]];

该语句对交互式SELECT语句的扩充就是多了一个INTO 子句。把 从数据库中找到的符合条件的纪录,放到INTO 子句指出的主变量中去。其他子句的含义不变。使用该语句需要注意以下几点:

1.            INTO 子句,WHERE子句的条件表达式,HAVING短语的条件表达式中均可以使用主变量。

2.            查询返回的纪录中,可能某些列为空值 NULL。如果INTO 子句中主变量后面跟有指示变量,则当查询得出的某个数据项为空值时,系统会自动将相应主变量后面的指示变量置为负值,而不再向该主变量赋值,即主变量值仍为执行SQL语句之前的值。所以当指示变量值为负值时,不管主变量为何值,均应认为主变量值为NULL。指示变量只能用于INTO子句中。

3.            如果数据库中没有满足条件的纪录,则DBMS将SQLCODE的值置为100。

4.            如果查询结果实际上并不是单条纪录,而是多条纪录,则程序出错,DBMS会在SQLCA中返回错误信息。

例. 查询某个学生选修某门课程的成绩。假设已将要查询的学生的学号赋给了主变量givensno,将课程号赋给了主变量givencno.

  EXEC SQL SELECT Sno,Cno,Grade

             INTO :Hsno, :Hcno, :Hgrade:Gradeid

             FROM  SC

             WHERE  Sno=:givensno AND Cno=:givencno;

由于学生选修一门课后有可能没有参加考试,也就是说其成绩为空值,所以在INTO子句中加了值是变量Gradeid,用于指示主变量Hgrade是否为空值。执行此语句后,如果Gradeid小于0,则不论Hgrade为何值,均认为该学生成绩为空值。

五.        非CURRENT 形式的UPDATE语句

   在UPDATE语句中,SET子句和WHERE子句中均可以使用主变量,其中SET子句中还可以使用指示变量。

例 将全体学生1号课程的考试成绩增加若干分。假设增加的分数已赋给主变量Raise.

    EXEC  SQL  UPDATE SC

         SET  Grade= Grade+:Raise

         WHERE Cno=’1’;

六.        非CURRENT 形式的DELETE语句

  DELETE语句的WHERE子句中可以使用主变量指定删除条件。

  例。某个学生退学了,现要将有关他的所有选课纪录删除掉。假设该学生的姓名已赋给主变量stdname.

   EXEC SQL DELETE

              FROM  SC

              WHERE Sno=

                     (SELECT Sno

                     FROM Student

                     WHERE Sname=:stdname);

另一种等价实现方法为:

         EXEC SQL DELETE

              FROM  SC

              WHERE :stdname=

                         ( SELECT Sname

                          FROM Student

                          WHERE Student.Sno=SC.Sno );

第1种方法更直接,从而也更高效些。

七.        INSERT 语句

   INSERT语句的VALUES子句中可以使用主变量和指示变量。

1.4 使用游标的SQL语句

   必须使用游标的SQL语句有:

       查询结果为多条纪录的SELECT语句

       CURRENT 形式的UPDATE语句

       CURRENT 形式的DELETE语句

一.  查询结果为多条纪录的SELECT语句

    一般情况下,SELECT语句查询结果都是多条纪录的,而高级语言一次只能处理一条纪录,因此需要用游标机制,将多条纪录一次一条送至宿主程序处理,从而把对集合的操作转换为对单个纪录的处理。

 使用游标的步骤为:

1.            说明游标。用DECLARE语句为一条SELECT语句定义游标。DECLARE语句的一般形式为:

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

 其中SELECT语句可以是简单查询,也可以是复杂的连接查询和嵌套查询。定义游标仅仅是一条说明性的语句,这时DBMS并不执行SELECT语句。

2.            打开游标。用 OPEN语句将定义的游标打开。OPEN语句的一般形式为:

EXEC SQL OPEN<游标名>;

打开游标实际上是执行相应的SELECT语句,把查询结果取到缓冲区中。这时游标处于活动状态,指针指向查询结果集中第一条纪录。

3.  推进游标指针并取当前纪录。用FETCH语句把游标指针向前推进一条纪录,同时将缓冲区中的当前纪录取出来送至主变量供主语言进一步处理。FETCH语句的一般形式为:

     EXEC  SQL  FETCH <游标名>

                   INTO  <主变量>[<指示变量>][,<主变量>[<指示变量>]]。。。。。;

   其中主变量必须与SELECT语句中的目标列表达式具有一一对应关系。

    FETCH语句通常用在一个循环结构中,通过循环执行FETCH语句逐条取出结果集中的行进行处理

4。关闭游标。用CLOSE 语句关闭游标,释放结果集占用的缓冲区及其他资源。CLOSE语句的一般形式为:

   EXEC  SQL  CLOSE <游标名> ;

二.        CURRENT形式的UPDATE语句和DELETE语句

UPDATE语句和DELETE语句都是集合操作,如果只想修改或删除其中某个纪录,则需要用带游标的SELECT语句查出所有满足条件的纪录,从中进一步找出要修改或删除的纪录,然后用CURRENT形式的UPDATE语句和DELETE语句修改或删除之。具体步骤是:

1.            用 DECLARE 语句说明游标。如果是为CURRENT形式的UPDATE语句做准备,则SELECT语句中要用

FOR  UPDATE  OF <列名>

      用来指明检索出的数据在指定列是可修改的。如果是为CURRENT形式的DELETE语句做准备,则不必使用上述子句。

2.            用OPEN语句打开游标,把所有满足查询条件的记录从指定表取到缓冲区中。

3.            用FETCH语句推进游标指针,并把当前纪录从缓冲区中取出来送至主变量。

4.            检查该纪录是否是要修改或删除的纪录。如果是,则用UPDATE语句或DELETE语句修改或删除该纪录。这时UPDATE语句和DELETE语句中要用子句

WHERE  CURRENT  OF  <游标名>

来表示修改或删除的是最后一次取出的纪录,即游标指针指向的纪录。

       第3,4步通常用在一个循环结构中,通过循环执行FETCH语句,逐条取出结果集中的行进行判断和处理。

   5.处理完毕用CLOSE语句关闭游标,释放结果集占用的缓冲区和其他资源。

                动态 SQL简介

嵌入式SQL语句为编程提供了一定的灵活性,使用户可以在程序运行过程中根据实际需要输入WHERE 子句或HAVING子句中某些变量的值。这些SQL语句的共同特点是,语句中主变量的个数与数据类型在预编译时都是确定的,只有主变量的值是程序运行过程中动态输入的,称这类嵌入式SQL语句为静态SQL语句。

   动态SQL方法允许在程序运行过程中临时“组装” SQL语句,主要有三种形式:

1.            语句可变。允许用户在程序运行时临时输入完整的SQL语句。

2.            条件可变。对于非查询语句,条件子具有一定的可变性。

     对于查询语句,SELECT子句是确定的,即语句的输出是确定的,其他子句(如WHERE子句,HAVING短语)有一定的可变性,例如查询学生人数,可以是查询某个系的学生总人数,查询某个年龄段的学生人数等,这时SELECT子句的目标列表达式是确定的(COUNT(*)),但WHERE子句的条件是不确定的。

3.            数据库对象,查询条件均可变

    对于查询语句,SELECT子句中的列名,FROM子句中的表名或视图名,WHERE子句和HAVING短语中的条件等均可由用户临时构造,即语句的输入和输出可能都是不确定的。

这几种动态形式几乎可覆盖所有的可变要求。为了实现上述三种可变形式,SQL提供了相应的语句,例如EXECUTE  IMMEDIATE,  PREPARE, EXECUTE, DESCRIBE

 等。使用动态SQL技术更多的是涉及程序设计方面的知识,而不是SQL语言本身。

0 0
原创粉丝点击