1 / 30

Embedded SQL

Embedded SQL. -Software School of Hunan University- 2006.09. 利用高级语言的过程性结构来弥补 SQL 语言实现复杂应用方面的不足。 嵌入 SQL 的高级语言称为主语言或宿主语言。 在混合编程中, SQL 语句负责操作数据库,高级语言语句负责控制程序流程。 预编译方法:由 DBMS 的预处理程序对源程序扫描,识别出 SQL 语句,把它们转换成主语言调用语句,以使主语言编译器能识别它,最后由主语言编译器将整个源程序编译成目标码。. 嵌入式 SQL 的一般形式.

jenny
Download Presentation

Embedded SQL

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Embedded SQL -Software School of Hunan University- 2006.09

  2. 利用高级语言的过程性结构来弥补SQL语言实现复杂应用方面的不足。利用高级语言的过程性结构来弥补SQL语言实现复杂应用方面的不足。 • 嵌入SQL的高级语言称为主语言或宿主语言。 • 在混合编程中,SQL语句负责操作数据库,高级语言语句负责控制程序流程。 • 预编译方法:由DBMS的预处理程序对源程序扫描,识别出SQL语句,把它们转换成主语言调用语句,以使主语言编译器能识别它,最后由主语言编译器将整个源程序编译成目标码。

  3. 嵌入式SQL的一般形式 • 所有的嵌入式SQL语句都不得必须加前缀EXEC SQL • 例如: • 在C语言中: EXEC SQL <SQL语句> EXEC SQL DROP TABLE Student; • 在COBOL中:EXEC SQL <SQL语句> END-EXEC

  4. 嵌入式SQL与主语言的通信 • 向主语言传递SQL语句执行状态信息,使语言能够据此信息控制程序流程,用SQL通信区(SQLCA)实现。 • 主语言向SQL语句提供参数,主要用主变量(Host Variable)实现; • 将SQL语句查询数据库的结果交主语言进一步处理,主要用主变量和游标(Cursor)实现。

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

  6. SQL通信区 • 例如:在执行删除语句后,不同的执行情况SQLCA中有下列不同的信息: • 成功删除并有删除的行数(SQLCODE=SUCCESS) • 无条件删除警告信息 • 违反数据保护规则,拒绝操作 • 没有满足条件的行,一行也没有删除 • 由于各种原因,执行出错

  7. 主变量(Host Variable) • 主语言程序变量:主变量 • 输入主变量:由应用程序对其赋值,SQL语句引用 • 输出主变量:由SQL语句对其赋值或设置状态信息,返回给应用程序 • 一个主变量既可是输入主变量也可是输出主变量。

  8. 指示变量(Indicator Variable) • 指示变量:主变量附带的可选变量,是一个整型变量,用来”指示”所指主变量的值或条件。可以指示输入主变量是否为空,可以检测输出主变量是否为空值,值是否被截断。 • 所有主变量和指示变量必须在SQL语句 BEGIN DECLARE SECTION与END DECLARE SECTION之间进行说明。 • SQL语句的主变量名和指示变量前要加冒号作为标志,且指示变量必须紧随主变量之后。 • 在SQL语句之外,主变量和指示变量直接引用,不须加冒号。

  9. 游标(Cursor) • SQL语言面向集合,一条SQL语句原则上可以产生或处理多条记录,而主语言是面向记录的,一组主变量一次只能存放一条记录。所以仅用主变量不能完全满足SQL语句向应用程序输出数据的要求。 • 游标是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果,每个游标区都有一个名字。 • 用户可以通过游标逐一获得数据,并赋给主变量,交由主语言处理。

  10. 程序实例(SQL in C) EXEC SQL INCLUDE SQLCA; ……………………定义SQL通信区 EXEC SQL BEGIN DECLARE SECTION; ……….主变量说明开始 CHAR Sno(5) CHAR Cno(3) INT Grade; EXEC SQL END DECLARE SECTION; ……….主变量说明结束 Main() { EXEC SQL DECLARE C1 CURSOR FOR ……….定义游标 SELECT Sno, Cno, Grade FROM SC; EXEC SQL OPEN C1; ……….………. 打开游标 for( ; ; ) {

  11. 程序实例(SQL in C) EXEC SQL FETCH C1 INTO :Sno, :Grade; ……….推进游标指针并将当前数据放入主变量 if(sqlca.sqlcode<>SUCCESS ……….利用SQLCA中的状态信息决定何时退出循环 break; printf(“Sno:%s,Cno:%s,Grade:%d”,:Sno,:Cno, :Grade); ……….打印查询结果 } EXEC SQL CLOSE C1; ……….………. 关闭游标 }

  12. 不用游标的SQL语句 • 说明性语句 • 数据定义语句 • 数据(权限)控制语句 • 查询结果为单记录的SELECT语句 • 非CURRENT形式的UPDATE语句 • 非CURRENT形式的DELETE语句 • INSERT语句 不需要使用主变量 通常需要使用主变量

  13. 查询结果为单记录的SELECT语句 EXEC SQL SELECT [ALL|DISDINCT] < 目标列表达式1>…… INTO <主变量>[<指示变量>]…… FROM <表名或视图名>,…… [ WHERE<Condition>] [GROUP BY<列名>[HAVING<条件表达式>]] [ORDER BY<列名>[ASC|DESC]] • INTO子句、WHERE子句、HAVING短语的条件表达式中均可用主变量 • 当查询得出某个数据项为空时,系统会自动将相应主变量后的指示变量置为负值,而不再向该主变量赋值,即主变量仍为执行SQL语句之前的值,所以当指示变量为负值时,不管主变量为何值,均应认为主变量为NULL。指示变量只能用于INTO子句中。

  14. 查询结果为单记录的SELECT语句 • 如果数据库没有满足条件的记录,则DBMS将SQLCODE的值置为100。 • 如果查询结果实际上并不是单条记录,而是多条记录,则程序出错,DBMS会在SQLCA中返回错误信息。 • 例:根据学号查学生信息 EXEC SQL SELECT Sno, Sname, Ssex,Sage,Sdept INTO :Hsno, :Hname, :Hsex, : Hage, :Hdept FROM Student WHERE Sno=:givensno;

  15. 查询结果为单记录的SELECT语句 • 例:查询某个学生的某门课程成绩 EXEC SQL SELECT Sno, Cno, Grade INTO :Hsno, :Hcno, :Hgrade:Gradeid FROM SC WHERE Sno=:givensno AND Cno=:givencno; • 由于学生选修一门课后可能没有参加考试,也就是说成绩为空,所以在INTO子句中加了指示变量Gradeid,用于指示主变量是否为空值。

  16. 非CURRENT形式的UPDATE语句 • 在UPDATE语句中,SET子句和WHERE子句中均可以使用主变量,其中SET子句中还可以使用指示变量。 • 例:将全体学生的1号课程成绩增加若干分,假设增加的分数已赋值给主变量Raise. EXEC SQL UPDATE SC SET Grade=Grade+:Raise WHERE Cno=‘1’; EXEC SQL UPDATE SC SET Grade=:newgrade WHERE Sno=:givensno;

  17. 非CURRENT形式的UPDATE语句 • 例:将软件学院全体学生年龄置为空。 Sageid=-1; EXEC SQL UPDATE Student SET Sage=:Raise:Sageid WHERE Sdept=‘SS’; 由于将指示变量Sageid赋一个负值,因此无论Raise为何值,DBMS会将SS的所有学生年龄置为空值。 等价于: EXEC SQL UPDATE Student SET Sage=NULL WHERE Sdept=‘SS’;

  18. 非CURRENT形式的DELETE语句 • 可使用主变量指定删除条件。 • 例:某个学生退学了,删除其所有选课记录。 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);

  19. INSERT语句 • INSERT语句的VALUES子句可能使用主变量和指示变量 • 例:某个学生新选修了某门课程。假设学号赋值给了主变量stdno,课程号赋给了couno 。 gradeid=-1; EXEC SQL INSERT INTO SC(Sn0, Cno, Grade) VALUES(:stdno:couno, :gr:gradeid); 由于该学生刚选修课程,尚无考试成绩,所以把指示变量gradeid置为负值。

  20. 使用游标的SQL语句 • 查询结果为多条记录的SELECT语句 • CURRENT形式的UPDATE语句 • CURRENT形式的DELETE语句

  21. 查询结果为多条记录的SELECT语句 • 使用游标的步骤: (1)说明游标 EXEC SQL DELCARE<游标名> CURSOR FOR <SELECT语句>; (2)打开游标:执行相应的SELECT语句,把结果取到缓冲区中,这时游标处于活动状态,指针指向结果集中第一条记录。 EXEC SQL OPEN<游标名>; (3)推进游标指针并取当前记录。 EXEC SQL FETCH<游标名> INTO <主变量>[<指示变量>]……; 主变量名必须与SELECT语句中的目标列表达式一一对应。 FETCH语句通常用在一个循环结构中,通过循环逐条取出记录处理。 (4)关闭游标,释放结果集占用的缓冲区和其他资源。 EXEC SQL CLOSE<游标名>

  22. 查询结果为多条记录的SELECT语句 • 例:查询某个系全体学生的信息。要查询的系名由用户指定,存放在主变量deptname中。 …… EXEC SQL BEGIN DELCARE SECTION; …… /*说明主变量deptname,Hsno,Hsname,Hssex,Hsage等*/ EXEC SQL END DECLARE SECTION; …… gets(deptname); /*为主变量deptname赋值*/ …… EXEC SQL DECLARE SX CURSOR FOR /*说明游标SX,将SX SELECT Sno, Sname, Ssex, Sage 与查询结果集相联系*/ FROM Student WHERE Sdept=:deptname;

  23. 查询结果为多条记录的SELECT语句 EXEC SQL OPEN SX WHILE(1) /*用循环结构逐条处理结果集中的记录*/ { EXEC SQL FETCH SX INTO :Hsno, Hsname, :Hssex, :Hsage; if(sqlca.sqlcode<>SUCCESS) break; /*若查询结果处理完或出现错误,则退出循环*/ …… }; EXEC SQL CLOSE SX;

  24. 查询结果为多条记录的SELECT语句 • 例:查询某个系全体学生的选课信息。 …… EXEC SQL BEGIN DELCARE SECTION; …… /*说明主变量deptname,Hsno,Hsname,Hssex,Hsage等*/ EXEC SQL END DECLARE SECTION; …… EXEC SQL DECLARE SX CURSOR FOR /*说明游标SX,将SX SELECT Sno, Sname, Ssex, Sage 与查询结果集相联系*/ FROM Student WHERE Sdept=:deptname;

  25. 查询结果为多条记录的SELECT语句 WHILE(gets(deptname!=NULL)) /*接收变量deptname的值*/ { /*处理deptname指定系的学生信息,每次循环中deptname可不同*/ EXEC SQL OPEN SX WHILE(1){ EXEC SQL FETCH SX INTO :Hsname, :Hssex, :Hsage; if(sqlca.sqlcode<>SUCCESS) break; /*若查询结果处理完或出现错误,则退出循环*/ …… }; EXEC SQL CLOSE SX; }; ……

  26. CURRENT形式的UPDATE语句和DELETE语句 • UPDATE和DELETE语句都是集合操作,如果只想修改或删除其中的某个记录,则需要用带游标的SELECT语句查出所有满足条件记录,从中进一步找出要修改或删除的记录,然后用CURRENT形式的UPDATE和DELETE语句处理。 • 具体步骤: (1)用DELCARE语句说明游标。如果是为CURRENT形式的UPDATE语句作准备,则SELECT语句中要用 FOR UPDATE OF<列名>用来指明查询出的数据在指定列是可修改的。如果是为CURRENT形式的DELETE语句作准备,则不必使用上述子句。

  27. CURRENT形式的UPDATE语句和DELETE语句 (2)用OPEN语句打开游标,把所有满足条件的记录从指定表中取到缓冲区中; (3)用FETCH语句推进游标,并把当前记录从缓冲区中取出来送至主变量; (4)检查该记录是否为该修改或删除的记录。如果是,则修改或删除之。这时UPDATE和DELETE语句中要用子句 WHERE CURRENT OF<游标名>,表示修改或删除的是最近一次取出的记录,即游标指针指向的记录。 第(3)和(4)步通常用在一个循环结构中,通过循环执行FETCH语句,逐条取出结果集中的记录进行判断和处理。 (5)处理完毕后,用CLOSE语句关闭游标,释放缓冲区和其他资源。

  28. CURRENT形式的UPDATE语句 • 查询某个系全体学生信息,然后根据用户要求修改其中某些记录的年龄字段。 …… EXEC SQL BEGIN DELCARE SECTION; …… /*说明主变量deptname,Hsno,Hsname,Hssex,Hsage, NEWage等*/ EXEC SQL END DECLARE SECTION; …… gets(deptname); EXEC SQL DECLARE SX CURSOR FOR SELECT Sno, Sname, Ssex, Sage FROM Student WHERE Sdept=:deptname; FOR UPDATE OF Sage;

  29. CURRENT形式的UPDATE语句 EXEC SQL OPEN SX WHILE(1){ /*用循环结构逐条处理结果集中的记录*/ EXEC SQL FETCH SX INTO :Hsno, Hsname, :Hssex, :Hsage; if(sqlca.sqlcode<>SUCCESS) break; /*若查询结果处理完或出现错误,则退出循环*/ printf(“%s,%s,%s,%d”, sno, sname, ssex, sage); printf(“UPDATE AGE?”); /*问用户是否需要修改*/ scanf( “%c”, &yn); if(yn=‘y’ or yn=‘Y’) /*需要修改*/ { printf(“INPUT NEW AGE:”); scanf(%d”, &NEWage); EXEC SQL UPDATE Student SET Sage = :NEWage WHERE CURRENT OF SX; }; …… }; EXEC SQL CLOSE SX;

  30. CURRENT形式的UPDATE语句和DELETE语句 • 当游标定义中的SELECT语句带有UNION或ORDER BY子句时,或者该SELECT语句相当于定义一个不可变更的视图时,不能使用CURRENT形式的UPDATE和DELETE语句。

More Related