美文网首页
数据库系统概论 实验五 通过嵌入式SQL访问数据库

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

作者: 北北南北 | 来源:发表于2018-05-23 08:38 被阅读193次

    一、实验目的

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

    二、实验平台和实验工具

    • 在KingbaseES数据库管理系统上,通过C语言编写访问数据库的应用程序来对数据库进行各种数据操作。
    • 编程工具VC++6.0
    • 另需要32位KingbaseES的lib库,后会详细说明。

    三、实验内容和要求

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

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

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

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

    1.嵌入式SQL

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

    2.KingbaseES预处理器

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

    • esqlc详细的语法格式以及参数意义,请参阅联机帮助。
    • 要求程序文档名的后缀为.pc,可以省略。
    • 预编译后得到的文档,与程序文档同名,后缀为.c;放在与程序文档同一个路径下。
      esqlc.exe存在KingbaseES的安装目录的Basesoft\KingbaseES\4.1\bin下。例如,KingbaseES的安装目录是C:\Program Files,那么eslqc.exe则在C:\Program Files\Basesoft\KingbaseES\ 4.1\bin下。
      注意:在安装SQL Server时并不会同时安装预编译应用程序nsqlprep.exe,需要将此文件另拷贝至安装目录下;而KingbaseES在安装时会同时安装此文件,因此不需要另外拷贝

    3.预编译

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

    • 在linux环境下

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

    • 在windows环境下

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

    4.编译和链接

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

    • 在linux环境下
      假定预编译完成后生成的C程序为authid.c。在linux环境下编译和链接该C程序的具体方法如下:
      1.编译.c程序
      % gcc authid.c -c -o authid.o -I /usr/local/kingbase/include
      2.链接,生成可执行文件
      % gcc authid.o -o basetab.out -I /usr/local/kingbase/include -L /usr/local/kingbase/lib -lecsys –lpq

    • 在windows环境下
      我们假定预编译生成的authid.c存放在Basesoft\KingbaseES\4.1\bin目录下。我们使用命令行形式对该程序进行编译和链接,具体方法如下:
      1.编译.c程序
      cl /c /DWIN32 /I"C:\Program Files\Basesoft\KingbaseES\4.1\include" /Foauthid.obj authid.c
      2.链接,生成可执行文件
      link /out:authid.exe authid.c "C:\Program Files\Basesoft\KingbaseES\4.1\lib\esql.lib

    四、实验步骤

    1.下载相关文件

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

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

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

    • 选择 Tools->选项->目录->include files:
      把本地安装Kingbase的include目录路径加入中间的列表框,并放在首位。

    • 选择 Tools->选项->目录->library files:
      将32位Kingbase的lib目录路径(或者下载的lib文件目录)加入,同样放在首位。

    • 选择 Project->设置->连接:
      在对象/库模块中:手打添加一个esql.lib,加在最前面就行。

    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文件

    相关文章

      网友评论

          本文标题:数据库系统概论 实验五 通过嵌入式SQL访问数据库

          本文链接:https://www.haomeiwen.com/subject/ucvljftx.html