一、实验目的
熟悉通过嵌入式SQL(主语言为C语言)编程访问数据库。
二、实验平台和实验工具
- 在KingbaseES数据库管理系统上,通过C语言编写访问数据库的应用程序来对数据库进行各种数据操作。
- 编程工具VC++6.0
- 另需要32位KingbaseES的lib库,后会详细说明。
三、实验内容和要求
熟悉RDBMS的预编译程序。通过嵌入式SQL编程访问数据库的基本步骤,
对学生课程数据库中的表,完成下面功能(你也可以自己给出功能要求):
查询某一门课程的信息。要查询的课程由用户在程序运行过程中指定,放在主变量中。
查询选修某一门课程的选课信息,要查询的课程号由用户在程序运行过程中指定,放在主变量中,然后根据用户的要求修改其中某些记录的成绩字段。
要求:提交源程序并标识必要的注释。保证程序能正确编译和运行,认真填写实验报告。
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
点击百度云下载32位Kingbase或者直接下载我安装好后的拿出来的lib文件
点击百度云下载lib
这我没试过,理论是可行的。毕竟安装个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.编译和链接
打开VC++,创建一个空的控制台程序
将刚才生成好的.c文件,添加到项目中,编译执行。
不出意外会出现丢失dll文件的错误,把所有需要的dll文件,从kingbase的lib中复制到项目的DEBUG目录中。
(代码,我已经编译成功过了,不会出现语法错误,若是语法错了,应该是修改了PC文件导致的错,根据报错信息,到相应行查看哪里出了问题)-
执行,并查看数据库的变化:
实验前后对比
五、实验中的问题
C:\PROGRAM FILES\MYSQL\MYSQL SERVER 5.7\LIB\libmysql.lib : fatal error LNK1113: invalid machine type
原因:安装的64位的Kingbase和32位的程序不匹配,安装32位的Kingbase。
- 无法启动此程序因为计算机中丢失limysql.dll
将dll文件放在项目的Debug中。
- 计算机丢失ESQL.dll、kci.dll、intl.dll、ectypes.dll。程序启动失败。
通通从lib文件夹中复制到debug目录下。程序执行成功。
程序成功启动,但卡住不动。
PC文件中的问题:
test.pc(34) : error C2065: 'SQLCA' : undeclared identifier
全改成小写,有别样的惊喜。
-
LINK : fatal error LNK1168: cannot open Debug/esql_test.exe for writing
是由于前一次调试运行是最后没有按任意键退出程序,而是点“关闭”按钮关cmd窗口的,vc6.0++有bug的 ,点关闭按钮有时后会导致窗口被关闭了但是程序进程还在运行。
打开任务管理器,关掉该进程。
- 程序运行成功,但数据库操作无反应。
Please choose the department name(CS/MA/IS):IS 数据处理结束!Press any key to continue
SQL语句不对,大小写敏感。顺便添加一个判断语句。如果
sqlca.sqlcode != 0
,就说明嵌入式SQL语句执行失败了。
- 关于SQL语句,记得改成大写。
毕竟kingbase不管大写小写,都给改成大写了。
六、实验总结
改了一晚上的pc文件...