Prayer

在一般中寻求卓越
posts - 1256, comments - 190, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

厦门大学的一个课件  备查
http://www.cs.xmu.edu.cn/education/fine_courses/database/%BE%AB%C6%B7%BF%CE%B3%CC%BD%A8%C9%E8%C4%DA%C8%DD/3_%CD%F8%C2%E7%B0%E6cai/content/index.htm


           

3. 不用游标的嵌入式SQL语句应用技术

             
 

     所谓不用游标的SQL语句,是指一般不需要返回结果数据,也不需要使用主变量的语句。它们是嵌入式SQL中最简单的一类语句。有以下几种:
       · 说明性语句
       · 数据定义语句
       · 数据控制语句
       · 查询结果为单记录的SELECT语句
       · 非CURRENT形式的UPDATE语句
       · 非CURRENT形式的DELETE语句
       · INSERT语句
    其中:

    *) 所有的说明性语句、数据定义与控制语句都不需要使用游标,在主语言中嵌入说明性语句、数据定义与控制语句,只要给语句加上前缀EXEC SQL和语句结束符即可。

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

    *) SELECT语句、UPDATE语句、DELETE语句则更复杂些。

   以下分别讨论常见的几种使用方法:
 

 一、说明性语句
 

    

   交互式SQL中没有说明性语句,这里的说明性语句是专为在嵌入式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 :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子句指出的主变量中去。其他子句的含义不变。使用该语句需要注意以下几点:
   *) INTO子句、WHERE子句的条件表达式、HAVING短语的的条件表达式中均可以使用主变量,但这些主变量必须事先加以说明,并且引用时前面要加上冒号。
   *) 查询返回的记录中,可能某些列值为空值NULL,则如下处理:如果INTO子句中主变量后面跟有指示变量,则当查询得出的某个数据项为空值时,系统会自动将相应主变量后面的指示变量置为负值,但不向该主变量执行赋值操作,即主变量值仍保持执行SQL语句之前的值。所以当发现指示变量值为负值时,不管主变量为何值,均应认为主变量值为NULL。指示变量只能用于INTO子句中,并且也必须事先加以说明,引用时前面要加上冒号。
   *) 如果数据库中没有满足条件的记录,即查询结果为空,则DBMS将SQLCODE的值置为100。
   *) 如果查询结果实际上并不是单条记录,而是多条记录,则程序出错,DBMS会在SQLCA中返回错误信息。

例3 根据学生号码查询学生信息。假设已将要查询的学生的学号赋给了主变量givensno


EXEC SQL SELECT Sno, Sname, Ssex, Sage, Sdept
    INTO :Hsno, :Hname, :Hsex, :Hage, :Hdept
    FROM Student
    WHERE Sno=:givensno;


上面的SELECT语句中Hsno, Hname, Hsex, Hage, Hdept和givensno均是主变量,并均已在前面的程序中说明过了。

例4 查询某个学生选修某门课程的成绩。假设已将要查询的学生的学号赋给了主变量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为何值,均认为该学生成绩为空值。


虽然对于仅返回一行结果数据的SELECT语句可以不使用游标,但从应用程序独立性角度考虑,最好还是使用游标。因为如果以后数据库改变了,该SELECT语句可能会返回多行数据,这时不使用游标就会出错。
 

 
五、非CURRENT形式的UPDATE语句
 

 非CURRENT形式是指特殊情况下的应用。在这种情况下的嵌入式UPDATE语句中,SET子句和WHERE子句都可以使用主变量,其中SET子句中还可以使用指示变量。以下分别用几个例子说明它们的应用技术:


例5 将全体学生1号课程的考试成绩增加若干分。假设增加的分数已赋给主变量Raise
EXEC SQL UPDATE SC
    SET Grade=Grade+:Raise
    WHERE Cno='1';

该操作实际上是一个集合操作,DBMS会修改所有学生的1号课程的Grade属性列。

例6 修改某个学生1号课程的成绩。假设该学生的学号已赋给主变量givensno,修改后的成绩已赋给主变量newgrade
EXEC SQL UPDATE SC
    SET Grade=:newgrade
    WHERE Sno=:givensno;

例7 将计算机系全体学生年龄置NULL值
Sageid=-1;
    EXEC SQL UPDATE Student
    SET Sage=:Raise:Sageid
    WHERE Sdept='CS';

将指示变量Sageid赋一个负值后,无论主变量Raise为何值,DBMS都会将CS系所有记录的年龄属性置空值。它等价于:
EXEC SQL UPDATE Student
    SET Sage=NULL
    WHERE Sdept='CS';
 

 
六、非CURRENT形式的DELETE语句
 

    

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


例8 某个学生退学了,现要将有关他的所有选课记录删除掉。假设该学生的姓名已赋给主变量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 Studnet.Sno=SC.sno);

显然第一种方法更直接,从而也更高效些。
如果该学生选修了多门课程,执行上面的语句时,DBMS会自动执行集合操作,即把他选修的所有课程都删除掉。
 

 
七、INSERT语句
 

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


例9 某个学生新选修了某门课程,将有关记录插入SC表中。假设学生的学号已赋给主变量stdno,课程号已赋给主变量couno。


gradeid=-1;
EXEC SQL INSERT
    INTO SC(Sno, Cno, Grade)
    VALUES(:stdno, :couno, :gr:gradeid);


由于该学生刚选修课程,尚未考试,因此成绩列为空。所以本例中用指示变量指示相应的主变量为空值。
 

 

厦门大学计算机科学系  薛永生


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理