数据库编程

数据库编程


嵌入式 SQL

  • 嵌入式 SQL 的处理过程
    将 SQL 语句嵌入到程序设计语言中 , 如 C,C++,Java

    为了能区分 SQL 语句与主语言语句,所有 SQL 语句都必须加前缀 EXEC SQL, 以(;)结束成为一个程序片段
    EXEC SQL ;


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

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

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

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

  • SQL 通信区
    SQLCA 中有一个变量 SQLCODE ,用来存放每次执行 SQL 语句后返回的代码
    应用程序每执行完一条 SQL 语句之后都应该测试一下 SQLCODE 的值,以了解该 SQL 语句执行情况并做相应处理,如果SQLCODE 等于预定于的常量 SUCCESS, 则表示 SQL 语句成功,否则 SQLCODE 存放错误代码,程序员可以根据错误代码查找问题。

  • 主变量
    SQL 语句中使用的 主语言 程序变量称为主变量
    输入主变量:应用程序对其赋值,SQL 语句引用
    输出主变量:由SQL 语句对其赋值或设置状态信息,返回给应用信息
    指示变量:属于整形变量,用来“指示”所指变量的值或者条件。可以指示输入主变量是否为空值,可以检测输出主变量是否为空值,值是否被截断。

    主变量和指示变量的表现形式:
    :变量名

  • 游标
    游标是系统为用户开设一个数据缓冲区,存放 SQL 语句的执行结果,每个游标区 都有一个名字,用户可以通过游标逐一获取记录,并赋给主变量,交由主语言进一步处理

  • 建立和关闭数据库链接
    建立链接语句
    EXEC SQL CONNECT TO target[AS connection-name,[USER user-name]]
    target : 数据服务器
    connect-name 可选链接名,链接必须是一个有效的标识符,主要用来识别一个程序内同时建立的多个链接,如果在整个程序内只有一个链接也可以不指定链接名。

  • 关闭数据库链接
    EXEC SQL DISCONNECT [connection];

  • 程序示实例
    例: 一次检查某个系的学生记录,交互式更新某些学生年龄

    EXEC SAL BEGIN DECLARE SECTION; /* 主变量说明开始*/
    char deptname[20];
    char HSno[9];
    char HSage;
    int NEWAGE;
    EXEC SQL END DECLARE SECTION /* 主变量说明结束 */
    long SQLCODE;
    EXEC SQL INCLUDE sqlea; /* 定义 SQL 通信区 */
    int main(void)          /* C 语言主程序开始 */
    {
    int count =0;
    char yn;                /* 变量 yn 代表 yes 或 no */
    printf("Please choose the department name(CS/MA/IS):");
    sacnf("%s",&deptname);  /* 为主变量 deptname 赋值 */
    EXEC SQL CONNECT TO TEST@localhost:54321 USER "SYSYTEM"/"MANACER" /* 链接数据库 TEST */
    EXEC SQL DECLARE SX CURSOR FOR  /* 定义游标 SX */
        SELECT Sno,Sname,Ssex,Sage  /* SX对应的语句 */
        FROM Student
        WHERE SDept = :deptname; 
    }
    EXEC SQL OPEN SX;               /* 打开游标SX,指向查询结果的第一行 */
    for(;;)
    {
        EXEC SQL FETCH SX INTO:HSno,:HSno,:HSname,:HSnex,:HSage; /* 推进游标,将当前数据放入主变量 */
        if (sqlea,sqlcode != 0)         /* sqlcode != 0 表示操作不成功 */
            break;                      /* 利用 SQLCA 中的状态信息决定何时退出循环 */
    
        if (count ++==0)                /* 如果是第一行的话,先打出行头 */
        printf("\n %-10s %20s  % -10s% -10s\n","Sno","Sname","Sage");
        print("%-10s% - 20s% - 10s % - 10d\n",Hsno,HSname,HSex,HSage); /* 打印查询结果 */
        pintf("UPDATE ACE(y/n)?");  /* 询问用户是否要更新该学生的年龄 */
        do{
        scanf(%c,&yn);
        }
        while(yn!='N'&&yn!="n"&& YN!= 'Y'&&yn!="y");
        if(yn=='y'||yn=="Y")/* 如果选择更新操作 */
        {
            printf("INPUT NEW ACE:");
            scanf("%d",&NEWAGE);    /* 用户输入新年龄到主变量中 */
            EXEC SQL UPDATE Student     /* 嵌入式 SQL 更新语句 */
                        SET Sage = :NEWAGE
                        WHERE CURRENT OF SX; /* 对当前游标指向的学生年龄进行更新 */
        }
    }
    EXEC SQL CLOSE SX;          /* 关闭游标 SX 不再和查询结果对应 */
    EXEC SQL COMMIT WORK;       /* 提交更新 */
    EXEC SQL DISCONNECT TEST;   /* 断开数据库链接 */
    

不用游标 的 SQL 语句

不需要使用游标的 SQL 语句:说明性语句、数据定义语句、数据控制语句、查询结果为单记录的SELECT 语句、非 CURRENT 形式的增删改语句。
  • 查询结果为单位记录的 SELECT 语句
    例:根据学生号码查询学生信息,假设已经把要查询的学生的学号赋给了主变量 givensno

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

    要注意:
    1. INTO 子句、WHERE 子句和 HAVING 短语的条件表达式中 均可以使用主变量
    2. 查询结果为空值的处理
    指示变量只能用于 INTO 子句中

  • 非 CURRENT 形式的增删改语句
    有些增删改语句不需要使用游标,不是 CURRENT 形式,在 UPDATE 的 SET 子句 和 WHERE 子句中可以使用主变量,SET 子句还可以使用指示变量

    例:修改某个学生选修 1 号课程的成绩

        EXEC SQL UPDATE SC
            SET GRADE = :newgrade       /* 修改的成绩已赋给主变量 */
            WHERE Sno = :givensno;      /* 学号已赋给主变量 givensno */
    

    例: 将计算机系全体学生年龄置 NULL 值

    Sageid = -1;
    EXEC SQL UPDATE Student 
        SET Sage = :Raise :Sageid
        WHERE Sdept = 'CS'
    

    将指示变量 Sageid 赋一个负值后,无论主变量 Raise 为何值,RDBMS 都会将 CS 系所有学生的年龄置空值 等价于:

    EXEC SQL UPDATE Student
            SET Sage = NULL
            WHERE Sdept = 'CS';
    

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

    EXEC SQL DELETE 
            FROM SC
            WHERE Sno = 
                        (SELECT Sno
                         FROM Student
                         WHERE Sname = :stdnome);

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

    gradeid = -1                /* 用作只是变量,赋为负值 */
    EXEC SQL INSERT 
            INTO SC(Sno,Cno,Grade)
            VALUES(:stdno,:couno,:gr:gradeid);

由于该学生刚选修课程,成绩应为空,所以要把只是变量赋为负值


使用游标的 SQL 语句

必须使用游标的 SQL 语句有: 查询结果为 多条记录的 SELECT 语句、CURRENT 形式的 UPDATE 和 DELETE 语句

  • 查询记过为多条记录的 SELECT 语句
    使用游标的步骤
    • 说明游标:用 DECLARE 语句为一条 SELECT A语句定义游标
      EXEC SQL DECLARE <游标名> CURSOR FOR