数据库系统(上):模型与语言 战德臣主讲课堂笔记

第九讲 嵌入式SQL语言之基本技巧

2018-08-27  本文已影响0人  天际神游

嵌入式SQL语言

为什么需要嵌入式SQL语言?

交互式SQL本身不够灵活, 对于普通用户来说, 复杂的查询掌握起来太难, 开发应用程序很有必要. 而且查询本身具有复杂性, 若是能结合高级语言的流程控制等特性, 将会有很大优势.

高级语言中使用嵌入式语言需要解决的问题

程序与数据库连接

SQL语句在执行过程中,必须有提交和撤消语句才能确认其操作结果.

为什么需要提交和撤销?
先了解一下事务的概念:

事务

(从应用程序员角度)是一个存取或改变数据库内容的程序的一次执行,或者说一条或多条SQL语句的一次执行被看作一个事务.

事务一般是由应用程序员提出,因此有开始和结束, 结束前需要提交或撤消。

Begin Transaction
exec sql …
…
exec sql …
exec sql commit work | exec sql rollback work
End Transaction

在嵌入式SQL程序中,任何一条数据库操纵语句(如exec sql select等)都会引发一个新事务的开
始,只要该程序当前没有正在处理的事务。而事务的结束是需要应用程序员通过commit或
rollback确认的。因此Begin Transaction和End Transaction两行语句是不需要的。

事务, 就是提供一组操作, 要么全部执行, 要么全部不执行, 保证这个这组操作过程的完整性.

事务的特性:

嵌入式SQL示例:

#include <stdio.h>
#include “prompt.h”
exec sql include sqlca;  // SQLCA: SQL communication, Area SQL通信区
char cid_prompt[ ] = "Please enter customer id: ";
int main()
{ 
    exec sql begin declare section;       // 变量声明
    char cust_id[5], cust_name[14];    
    float cust_discnt;
    char user_name[20],user_pwd[20];
    exec sql end declare section;

    exec sql whenever sqlerror goto report_error;    // SQL错误捕获语句
    exec sql whenever not found goto notfound;       // SQL错误捕获语句

    strcpy(user_name, "poneilsql");    // 连接数据库
    strcpy(user_pwd, "*****");
    exec sql connect :user_name identified by :user_pwd;

    while((prompt(cid_prompt, 1, cust_id, 4)) >=0) {
        exec sql select cname,discnt
            into :cust_name, :cust_discnt
            from customers where cid=:cust_id;
        exec sql commit work;        // SQL Commit Wort

        printf("Customer’s name is %s and discount is %5.1f\n", cust_name,cust_discnt);
        continue;

        notfound: printf("Can’t find customer %s, continuing\n", cust_id);
    }
    exec sql commit release;
    return 0;

    report_error:
        print_dberror();      // 打印错误
        exec sql rollback release;  // 断开连接
        return 1;
}

游标

游标是什么? 我们为什么需要它?

检索单行结果,可将结果直接传送到宿主程序的变量中.例如:

exec sql select Sname, Sage into :vSname, :vSage from Student where Sname = :specName ;

检索多行结果, 就需要使用游标(Cursor)

游标

游标的使用:
游标(Cursor)的使用需要先定义、再打开(执行)、接着一条接一条处理,最后再关闭. 可以定义一次, 多次打开.

exec sql declare cur_student cursor for
    select Sno, Sname, Sclass from Student where Sclass='035101' ;
exec sql open cur_student;
exec sql fetch cur_student into :vSno, :vSname, :vSclass;
… …
exec sql close cur_student;

可滚动的游标

标准的游标总是从上往下的读的. 但是我们想向上向下滚动读取. ODBC(Open DataBase Connectivity)是一种跨DBMS的DB操作平台, 它在应用程序与实际的DBMS之间提供了一种通用接口, 可以帮助我们实现滚动游标.

数据库记录的删除与更新

删除

查找删除:

exec sql delete from customers c where c.city = 'Harbin' and
not exists ( select * from orders o where o.cid = c.cid);

定位删除:

exec sql declare delcust cursor for
    select cid from customers c where c.city =‘harbin’ and
        not exists ( select * from orders o where o.cid = c.cid)
     for update of cid;
exec sql open delcust
While (TRUE) {
    exec sql fetch delcust into :cust_id;
    exec sql delete from customers where current of delcust ; 
}
更新

一种是查找更新, 一种是定位更新
查找更新:

exec sql update student s set sclass = "035102"
    where s.sclass = "034101"

定位更新:

exec sql declare stud cursor for
    select * from student s where s.sclass ="034101"
    for update of sclass;
exec sql open stud
    While (TRUE) {
        exec sql fetch stud into :vSno, :vSname, :vSclass;
        exec sql update student set sclass = "035102" where current of stud ; 
    }

数据库插入

exec sql insert into student ( sno, sname, sclass)
    values ('03510128', '张三', '035101') ;

状态捕获及其处理

状态, 是嵌入式SQL语句的执行状态, 尤其指一些出错状态, 有时程序需要知道这些状态并对这些状态进行处理.
嵌入式SQL程序中, 状态捕获及处理有三部分构成:

SQL通信区: SQLCA

状态捕获语句

exec sql whenever condition action;
Whenever语句的作用是设置一个"条件陷阱", 当满足条件的时候, 就会执行相应的动作.


条件(condition)与动作(action)

作用范围, 两个whenever 之间, 否则直到程序结束.
注意:作用域是语句在程序中的位置,而不是控制流程(因是预编译程序处理条件陷阱)

回顾



数据库系统学习笔记

上一篇下一篇

猜你喜欢

热点阅读