数据库系统概论 实验五 通过嵌入式SQL访问数据库

2018-05-23  本文已影响193人  北北南北

一、实验目的

熟悉通过嵌入式SQL(主语言为C语言)编程访问数据库。

二、实验平台和实验工具

三、实验内容和要求

熟悉RDBMS的预编译程序。通过嵌入式SQL编程访问数据库的基本步骤,
对学生课程数据库中的表,完成下面功能(你也可以自己给出功能要求):

  1. 查询某一门课程的信息。要查询的课程由用户在程序运行过程中指定,放在主变量中。

  2. 查询选修某一门课程的选课信息,要查询的课程号由用户在程序运行过程中指定,放在主变量中,然后根据用户的要求修改其中某些记录的成绩字段。

要求:提交源程序并标识必要的注释。保证程序能正确编译和运行,认真填写实验报告。

1.嵌入式SQL

要求:将一段连续的SQL操作写成嵌入到C程序中的程序,调试程序,使得程序能完成一项复杂的数据处理功能,并提交程序。
嵌入式SQL由SQL语句和C/C++代码组成。其中SQL语句由预处理器翻译成C或C++的源代码。对预处理后的源代码进行编译、链接生成可执行程序后方可运行。

2.KingbaseES预处理器

KingbaseES的预处理程序是esqlc.exe。其常用的语法格式如下:

3.预编译

用KingbaseES预处理程序esqlc.exe对含有嵌入式SQL的程序文件进行预编译。如果编写的主程序文件名称为authid.pc,存放在C:\Program Files\Basesoft\KingbaseES\4.1\bin目录下,则预编译具体方法如下:

% ecsys authid.pc -o authid.c -I /usr/local/kingbase/include

esqlc -I "C:\Program Files\Basesoft\KingbaseES\4.1\include" -o authid.c authid.pc

4.编译和链接

当编译预处理过的C程序时,编译器需要查找ESQLC头文件,所以在编译时需要指定这些文件的路径。在链接时,该C程序需要链接esql.lib库,所以还要指定这个库文件的路径。
下面分别给出在linux和windows环境下,编译和链接该C程序的方法。

四、实验步骤

1.下载相关文件

VC++的32位控制台程序,与64位Kingbase的lib文件不兼容。需要下载32位的库文件。

这我没试过,理论是可行的。毕竟安装个32位的kingbase要占1G多内存,有点麻烦。

2.配置VC++中的MySQL头文件和库

3.预编译阶段--使用kingbase的预编译程序esqlc.exe

1. 编写嵌入式SQL文件,后缀改成pc,命名为test.pc,并修改其中的数据库和表信息。

#include<stdio.h>
#include<stdlib.h>

EXEC SQL BEGIN DECLARE SECTION;                 /*主变量说明开始*/
    char deptname[20];                          /*此处类型要与与创建的表结构保持一致*/
    char HSno[9];
    char HSname[20];
    char HSsex[2];
    int HSage; 
    int NEWAGE;
    
    char conn_str[256];
    varchar   uid[19];
    varchar   pwd[19];

EXEC SQL END DECLARE SECTION;                   /*主变量说明结束*/

long SQLCODE;
EXEC SQL INCLUDE sqlca;                         /*定义SQL通信区,与书上不同*/

int main(){                                     /*C语言主程序开始*/
    int count=0;
    char yn;                                    /*变量yn代表yes或no*/
    
    /*connect database
    EXEC SQL CONNECT TO  LAB@localhost:54321 USER "SYSTEM" IDENTIFIED BY "krms";*/
                                                /*连接数据库LAB*/
                                                /*根据自己情况更改*/
    strcpy(uid, "SYSTEM");
    strcpy(pwd, "krms");
    strcpy(conn_str, "LAB@localhost:54321");    /*我的数据库名LAB,记得大写*/
    EXEC SQL CONNECT TO :conn_str USER :uid IDENTIFIED BY :pwd; 
                                            
                                                
    if (sqlca.sqlcode == 0)
        printf("connect success!\n");
    else
    {
        printf("connect failed!再改改登录信息吧\n");
        return 0;
    }
    
    printf("Please choose the department name(CS/MA/IS):");
    scanf("%s",&deptname);                      /*为主变量deptname赋值*/

    EXEC SQL DECLARE SX CURSOR FOR              /*定义游标*/
        SELECT SNO,SNAME,SSEX,SAGE              /*SX对应语句的执行结果*/
        FROM STUDENT
        WHERE SDEPT=:deptname;
    EXEC SQL OPEN SX;                           /*打开游标SX便指向查询结果的第一行*/
    
    
    if (sqlca.sqlcode == 0)
        printf("查询成功!\n");
    else
    {
        printf("查询失败!再改改SELECT语句吧\n");
        return 0;
    }
    
    for(;;){                                    /*用循环结构逐条处理结果集中的记录*/
        EXEC SQL FETCH SX INTO :HSno,:HSname,:HSsex,:HSage;
                                                /*推进游标,将当前数据放入主变量*/
        if(sqlca.sqlcode!=0){                   /*sqlcode!=0,表示操作不成功,这里也表示查询完了,就退出*/
                                                /*并且此处和书上有点区别,需要改成小写,否则报错*/
                                                
            printf("数据处理结束\n");
            break;                              /*利用SQLCA中的状态信息决定何时退出循环*/
        }
        
        
        if(count++==0)                          /*利用SQLCA中的状态信息决定何时退出循环*/
            printf("\n%-10s%-22s%-4s%-10s\n","Sno","Sname","Ssex","Sage");
        
        printf("%-10s%-22s%-4s%-10d\n",HSno,HSname,HSsex,HSage);
                                                /*打印查询结果*/
        printf("UPDATE AGE(y/n)?");
        do{
            scanf("%c",&yn);
        }
        while(yn!='N'&&yn!='n'&&yn!='Y'&&yn!='y');
        if(yn=='y'||yn=='Y'){                   /*如果选择更新操作*/ 
            printf("INPUT NEW AGE:");
            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 LAB;                    /*断开LAB数据库连接*/ 
    return 0;
} 

2. 将test.pc存入kingbase安装目录D:/kingbase/es/v7/bin

3. 打开cmd,在此目录下,执行命令:

esqlc -I "D:\Kingbase\ES\V7\include" -o test.c test.pc

于是在该目录下得到编译好的.c文件。

4.编译和链接

  1. 打开VC++,创建一个空的控制台程序

  2. 将刚才生成好的.c文件,添加到项目中,编译执行。

  3. 不出意外会出现丢失dll文件的错误,把所有需要的dll文件,从kingbase的lib中复制到项目的DEBUG目录中。
    (代码,我已经编译成功过了,不会出现语法错误,若是语法错了,应该是修改了PC文件导致的错,根据报错信息,到相应行查看哪里出了问题)

  4. 执行,并查看数据库的变化:


    实验结果

实验前后对比

实验前后对比

五、实验中的问题

  1. C:\PROGRAM FILES\MYSQL\MYSQL SERVER 5.7\LIB\libmysql.lib : fatal error LNK1113: invalid machine type

原因:安装的64位的Kingbase和32位的程序不匹配,安装32位的Kingbase。

  1. 无法启动此程序因为计算机中丢失limysql.dll

将dll文件放在项目的Debug中。

  1. 计算机丢失ESQL.dll、kci.dll、intl.dll、ectypes.dll。程序启动失败。

通通从lib文件夹中复制到debug目录下。程序执行成功。

  1. 程序成功启动,但卡住不动。

  2. PC文件中的问题:
    test.pc(34) : error C2065: 'SQLCA' : undeclared identifier

全改成小写,有别样的惊喜。

  1. LINK : fatal error LNK1168: cannot open Debug/esql_test.exe for writing
    是由于前一次调试运行是最后没有按任意键退出程序,而是点“关闭”按钮关cmd窗口的,vc6.0++有bug的 ,点关闭按钮有时后会导致窗口被关闭了但是程序进程还在运行。

打开任务管理器,关掉该进程。

  1. 程序运行成功,但数据库操作无反应。
    Please choose the department name(CS/MA/IS):IS 数据处理结束!Press any key to continue

SQL语句不对,大小写敏感。顺便添加一个判断语句。如果sqlca.sqlcode != 0,就说明嵌入式SQL语句执行失败了。

  1. 关于SQL语句,记得改成大写。

毕竟kingbase不管大写小写,都给改成大写了。

六、实验总结

改了一晚上的pc文件...


改了一晚上的pc文件
上一篇下一篇

猜你喜欢

热点阅读