Chinaunix首页 | 论坛 | 博客
  • 博客访问: 455363
  • 博文数量: 724
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 5010
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 14:47
文章分类

全部博文(724)

文章存档

2011年(1)

2008年(723)

我的朋友

分类:

2008-10-13 16:58:29

MySQL数据库接口的VC实现与应用
作者:
(华东船舶工业学院 机械系,江苏 镇江 212003)

摘要:MySQL数据库作为一种网络数据库性能十分出色,但其在应用软件中使用较少。本文将主要探讨MySQL提供的两种数据库接口 ——(ODBC API和C API)在VC中的应用,并且形成一个类用以封装C API数据库接口的功能。

关键词:MySQL;数据库接口;ODBC API;C API

引言

随着现代计算机软硬件及网络技术的发展,在网上查找资料已成为现在获取信息的最重要手段之一。众所周知,所有的网上信息都是储存在网站数据库中的,这些信息的查询、更新等操作的功能则是由数据库服务器提供的,显然,数据库服务器的性能将直接关系到网站的生存。网站搭建中用的最多的数据库服务器是oracle和MySQL,前者功能强大,属于旗舰型数据库服务器,但前期投入太大;后者功能不断完善,简单易用而又不失性能,并且可以免费获得。因此,许多中小型网站的数据库服务器选用MySQL,而且,由于MySQL性能出色,一些大型网站也选用了MySQL。

由此可见,MySQL数据库服务器在网站建设中的表现是十分出色的。但是,正因为这样,几乎很少有人将MySQL用于应用软件的开发中。本文将详细介绍VC环境中MySQL数据库服务器不同接口的应用,并最终将产生一个CDatabase类封装MySQL数据库接口功能。

数据库接口实现与应用的计算机环境:硬件,C466、128M、15G;软件及操作系统,VISUAL C++ 6.0、MySQL 3.23.22-beta for win32、WIN98。

1 MySQL数据库简介

MySQL是一个真正的多用户、多线程SQL数据库服务器。SQL(结构化查询语言)是世界上最流行的和标准化的数据库语言,它使得存储、更新和存取信息更加容易。MySQL是一个客户机/服务器结构的实现,它由一个服务器守护程序mysqld和许多不同的客户程序以及库组成的。

MySQL的主要目标是快速、健壮和易用。最初是因为MySQL的创始人需要这样的一个SQL服务器,它能处理与任何不昂贵硬件平台上提供数据库的厂家在一个数量级上的大型数据库,但速度更快,MySQL因此就开发出来了。它提供C,C++,JAVA(JDBC),Perl,Python,PHP and TCL 的API接口;多平台支持,包括Solaris,SunOS,BSDI,SGI IRIX,AIX,DEC UNIX,Linux,FreeBSD,SCO OpenServer,NetBSD,OpenBSD,HPUX,Win9x and NT;多样的数据类型,包括有/无符号1,2,3,4,8字节integers,FLOAT,DOUBLE,CHAR,VARCHAR,TEXT,BLOB,DATE,DATETIME,YEAR,SET,ENUM;非常灵活和安全的权限系统,密码加密;为Windows提供ODBC接口,可通过Access与之相联,另有第三方开发商提供多样的 ODBC驱动程序;在MySQL 3.23中使用新MyISAM最大的表大小可达8百万 TB(2^63个字节);多种语言支持,但不支持中文。然而,为了实现快速、健壮和易用的目的,MySQL必须牺牲一部分灵活而强大的功能,如子查询、存储过程与触发器、外键、事物处理等。因而,MySQL在某些应用中缺乏灵活性,但这也使它对数据的处理速度较其它数据库服务器至少快2~3倍。

MySQL自身不支持Windows的图形界面,因此,所有的数据库操作及管理功能都只能在MS-DOS方式下完成。首先,必须登陆MySQL服务器,即在提示符\MySQL\BIN>下输入MYSQL –H host –U user –Ppassword,提示符改为mysql>时表示登陆成功。然后,选择所操作的数据库,即mysql> USE databasename。接着就可以用SQL语句进行查询了。如果需要退出数据库服务器,可执行QUIT命令,这样就成功退出服务器了。当然,由于MySQL的知名度日益增加,许多第三方软件公司推出了MySQL在Windows环境中的具有图形界面的支持软件,如EMS公司的EMS MYSQL MANAGER就提供了Windows形式的MySQL数据库操作功能。

2 利用ODBC API实现MySQL数据库功能调用

ODBC(Open Database Connectivity)即开放式数据库互联,作为Windows开放性结构的一个重要部分已经为很多的Windows程序员所熟悉,ODBC的工作依赖于数据库制造商提供的驱动程序,使用ODBC API的时候,Windows的ODBC管理程序把数据库访问的请求传递给正确的驱动程序,驱动程序再使用SQL语句指示DBMS(数据库管理系统)完成数据库访问工作,因此,ODBC的存在为我们开发应用数据库程序提供了非常强大的能力和灵活性。在Windows下可以对多种数据库安装ODBC数据库,用来连接数据库并访问它们的数据。

对于MySQL数据库服务器来说,它的制造商同样提供了相应的ODBC驱动程序,其最新版本为myodbc-2.50.31-win95。在WIN98环境下进行安装后,就可以利用编程语言通过ODBC API对MySQL数据库进行各种ODBC所支持的操作。因为ODBC屏蔽了各种数据库的差异,所以,原来用于对其它数据库进行操作的程序,通过ODBC同样能够对MySQL数据库进行操作。也就是说,ODBC使程序对数据库的通用性提高了。

用VC通过ODBC API对MySQL数据库进行编程,必须要对MySQL数据源进行设置,具体设置如图1:

图1 数据源设置信息

通过上图的设置,接着我们就可以按照一般的ODBC数据库编程方法,对MySQL数据库进行编程。

3 利用MySQL自带的C API函数实现数据库功能调用

由于各个数据库之间的差异,它们所提供的数据库功能也就各有不同。这样,通过ODBC API就不可能完全拥有所有的数据库功能,因而影响了程序对数据库的控制功能,也就不能充分发挥数据库的能力。并且这种统一的接口还是以损失效能为前提的,这就使数据库操作时间延长。所以,为了解决以上问题,MySQL的制造商在提供ODBC驱动程序的基础上,还提供了各种编程环境下的API,其中包括C API。这些API函数很显然能尽可能地发挥数据库的能力,并减少数据库操作的延长时间,但却使程序的通用性受到严重影响。

MySQL提供了一套C API函数,它由一组函数以及一组用于函数的数据类型组成,这些函数与MySQL 服务器进行通信并访问数据库,可以直接操控数据库,因而显著地提高了操控效能。

C API数据类型包括:MYSQL(数据库连接句柄)、MYSQL_RES(查询返回结果集)、MYSQL_ROW(行集)、MYSQL_FIELD(字段信息)、MYSQL_FIELD_OFFSET(字段表的偏移量)、my_ulonglong(自定义的无符号整型数)等;C API提供的函数包括:mysql_close()、mysql_connect()、mysql_query()、mysql_store_result()、mysql_init()等,其中mysql_query()最为重要,能完成绝大部分的数据库操控。

下面将具体讨论数据库操作类CDatabase通过C API的实现以及在VC中的应用。

3.1 CDatabase类的实现

CDatabase类封装了MySQL数据库的功能,因此不具备通用性,只能在对MySQL的应用程序中使用。下面将根据C++要求及规范给出CDatabase类的具体结构以及相关简要介绍:

class CDatabase  
{
public:
    BOOL UnLockTable();                     //解锁
    BOOL LockTable(char* TableName,char* PRIORITY);     //加锁
    int Reload();                           //重新登陆,非零时返回错误信息
    char* GetState();                       //服务器状态
    char* GetServerInfo();                  //服务器信息
    int GetProtocolInfo();                  //协议信息
    char* GetHostInfo();                        //主机信息
    char * GetClientInfo();                 //客户机信息
    char* GetFieldName(int FieldNum);       //字段名
    BOOL IsEnd();                           //是否最后
    int DropDB(char *db);                   //删除数据库,非零时返回错误信息
    void SeekData(int offset);              //查找指定数据
    int CreateDB(char *db);                 //创建数据库,非零时返回错误信息
    void FreeRecord();                      //释放结果集
    unsigned int GetFieldNum();             //得到字段数
    BOOL ConnectDB(Database_Param *p);      //连接数据库
    MYSQL_ROW GetRecord();                  //得到结果(一个记录)
    my_ulonglong GetRowNum();               //得到记录数
    BOOL SelectDB(Data_Param *para);            //选择数据库
    BOOL UpdateRecord(Data_Param *para);        //更新记录
    BOOL SelectRecord(Data_Param *para);        //选择记录
    BOOL InsertRecord(Data_Param *para);        //插入记录
    BOOL DelRecord(Data_Param *para);       //删除记录
    BOOL SelectAll(Data_Param *para);       //选择所有记录
    char * OutErrors();                     //输出错误信息
    CDatabase();                                //初始化数据库
    virtual ~CDatabase();                   //关闭数据库连接
 
private:
    MYSQL mysql;                                //数据库连接句柄
    MYSQL_RES *query;                       //结果集
    MYSQL_ROW row;                          //记录集
    MYSQL_FIELD *field;                     //字段信息(结构体)
    BOOL FindSave(char *str);               //查找并保存结果集
};
通过CDatabase类中定义的这些功能函数,我们可以通过远程或本机完成对MySQL数据库的绝大部分操控,并且由于定义了解锁和加锁功能,使得应用程序能够多线程或多进程地访问数据库,大大提高了效能。以上函数的具体功能都是通过调用C API函数实现的。

3.2 CDatabase类在VC中的应用

第一步 建立初始化MySQL对象,并且将其初始化。即定义CDatabase类对象,这样程序就会自动调用构造函数CDatabase(),完成初始化。

构造函数实现如下:

CDatabase::CDatabase ()
{
  mysql_init (&mysql);
}

完成初始化只需定义CDatabase类对象,即

CDatabase base;

第二步 连接服务器,并连接需要的数据库。即调用ConnectDB(Database_Param *p)函数,结构体Database_Param中存放数据库参数,包括主机名、用户名、密码、数据库名等。该函数如返回TRUE表示连接成功,否则表示失败。

连接函数实现如下:
BOOL CDatabase::ConnectDB(Database_Param *p)
{
if(!mysql_real_connect(&mysql,p->host,p->user,p->password,p->db,p->port,p->unix_socket,p->client_flag))
{     
  OutErrors();      // 输出错误信息
  return false;
}
    return true;
}
第三步 对数据库进行加锁。即调用LockTable(char* TableName,char* PRIORITY),对相应的表TableName完成相应属性PRIORITY的加锁,使程序兼容多线程功能。 加锁函数实现如下:
BOOL CDatabase::LockTable(char* TableName,char* PRIORITY)
{
    char str[50];
    sprintf(str,"LOCK TABLES %s %s",TableName,PRIORITY);
    if(mysql_query(&mysql,str))
        return false;
    return true;
}
第四步 完成数据库操作。即根据需要调用UpdateRecord(Data_Param *para)、SelectRecord(Data_Param *para)、InsertRecord(Data_Param *para)、DelRecord(Data_Param *para)等操作。其中的结构体Data_Param中存放数据库操作参数。上述两个结构体的定义在global.h中。 InsertRecord函数实现如下,其它实现方法相似:
BOOL CDatabase::InsertRecord(Data_Param *para)
{
  char str[80];
  sprintf(str,"insert into %s values(%s)",para->tab_name,para->insert_val);
  if(mysql_query(&mysql,str))
    return false;
  return true;
}
第五步 解锁数据库。即调用UnLockTable(),完成对上述被加锁的表的解锁。 解锁函数实现如下:
BOOL CDatabase::UnLockTable()
{   
  if(mysql_query(&mysql,"UNLOCK TABLES"))
     return false;
  return true;
}
第六步 关闭数据库连接。即调用析构函数~CDatabase(),关闭数据库,并自动释放初始化时定义的CDatabase类对象。 析构函数如下:
CDatabase::~CDatabase()
{   
  if(query)
     mysql_free_result(query);
  mysql_close(&mysql);
}
注意:在编译程序时,必须加入MySQL的库文件libmySQL.lib

4 MySQL性能测试

4.1 ODBC API

通过索引读取200万行:528秒
插入35万行: 750秒

4.2 C API

通过索引读取200万行:412秒
插入35万行:435秒

4.3 其它数据库(以MS_SQL为例,WINNT环境)

通过索引读取200万行:1634秒
插入35万行:4012秒

注:以上数据是多次测量的平均值,不可避免一定的误差,仅供参考。

5 结束语

MySQL作为一个免费的SQL数据库,虽然功能不够十分强大,且灵活性较差,但是,已经能够满足一般应用软件的要求,而且MySQL数据库的开发者也在力求使之更加完善。并且,由MySQL性能测试可以看出,它对数据的处理速度明显快于其它数据库服务器。因此,如果应用软件对数据库的性能要求较高,而同时对数据库操作的功能及灵活性的要求不是很高的话,并且前期投入资金较少时,MySQL数据库服务器不失为一个最佳的选择。


--------------------next---------------------

根本就运行不了啊,该加的文件都加了,结果还是这样啊.
D:\Vc Example\cdatabase\Database.cpp(87) : error C2440: 'return' : cannot convert from 'const char *' to 'char *'  Conversion loses qualifiers
D:\Vc Example\cdatabase\Database.cpp(142) : error C2065: 'mysql_create_db' : undeclared identifier
D:\Vc Example\cdatabase\Database.cpp(152) : error C2065: 'mysql_drop_db' : undeclared identifier
D:\Vc Example\cdatabase\Database.cpp(168) : error C2440: 'return' : cannot convert from 'const char *' to 'char *'  Conversion loses qualifiers
D:\Vc Example\cdatabase\Database.cpp(173) : error C2440: 'return' : cannot convert from 'const char *' to 'char *' Conversion loses qualifiers
D:\Vc Example\cdatabase\Database.cpp(183) : error C2440: 'return' : cannot convert from 'const char *' to 'char *' Conversion loses qualifiers
D:\Vc Example\cdatabase\Database.cpp(188) : error C2440: 'initializing' : cannot convert from 'const char *' to 'char *' Conversion loses qualifiers
Error executing cl.exe.
( WorldRedeemer 发表于 2006-12-26 10:16:00)
 
您的代码里为什么只有三个文件:global.h  Database.h
Database.cpp 
不知道mysql.h在哪里
请赐教,具体点行吗,我是新手。
谢谢! ( shanzhu 发表于 2006-5-10 0:00:00)
 
哦,还有大家把winsock.h
   放在mysql.h前面,否则会有sock错误, ( zqh7850430 发表于 2006-4-4 19:27:00)
 
有两点注意的,:
   1,记得加入mysql.h和winsock.h
      2,记得在设置里加入libmysql.lib wsock32.lib 
   然后还记得设置include 和lib文件夹,就可以了 ( zqh7850430 发表于 2006-4-4 18:35:00)
 
续前:
D:\mysql\test\test\Database.cpp(87) : error C2440: 'return' : cannot convert from 'const char *' to 'char *'
        Conversion loses qualifiers
D:\mysql\test\test\Database.cpp(142) : error C2065: 'mysql_create_db' : undeclared identifier
D:\mysql\test\test\Database.cpp(152) : error C2065: 'mysql_drop_db' : undeclared identifier
D:\mysql\test\test\Database.cpp(168) : error C2440: 'return' : cannot convert from 'const char *' to 'char *'
        Conversion loses qualifiers
D:\mysql\test\test\Database.cpp(173) : error C2440: 'return' : cannot convert from 'const char *' to 'char *'
        Conversion loses qualifiers
D:\mysql\test\test\Database.cpp(183) : error C2440: 'return' : cannot convert from 'const char *' to 'char *'
        Conversion loses qualifiers
D:\mysql\test\test\Database.cpp(188) : error C2440: 'initializing' : cannot convert from 'const char *' to 'char *'
        Conversion loses qualifiers


( vcbull 发表于 2005-10-24 10:38:00)
 
测试该类时出现如下错误,根据前人的错误提示也没能解决,请高手能否详细说明一下!
database.cpp
c:\program files\mysql\mysql server 5.0\include\mysql_com.h(175) : error C2146: syntax error : missing ';' before identifier 'fd'
c:\program files\mysql\mysql server 5.0\include\mysql_com.h(175) : error C2501: 'SOCKET' : missing storage-class or type specifiers
c:\program files\mysql\mysql server 5.0\include\mysql_com.h(175) : error C2501: 'fd' : missing storage-class or type specifiers
c:\program files\mysql\mysql server 5.0\include\mysql_com.h(339) : error C2065: 'SOCKET' : undeclared identifier
c:\program files\mysql\mysql server 5.0\include\mysql_com.h(339) : error C2146: syntax error : missing ')' before identifier 's'
c:\program files\mysql\mysql server 5.0\include\mysql_com.h(340) : error C2059: syntax error : ')'
( vcbull 发表于 2005-10-24 10:37:00)
 
ckp:编译错误的朋友看过来...
×××要 助×××
error C2146: syntax error : missing ';' before identifier 'fd'
error C2501: 'SOCKET' : missing storage-class or type specifiers
error C2501: 'fd' : missing storage-class or type specifiers
error C2065: 'SOCKET' : undeclared identifier
按照ckp文中指示做好这些工作后,还是有上述错误提示。根据mysql所带的examples\libmysqltest例子的启发,似乎需要在#include 之前要加#include 
×××要 助×××
( shape 发表于 2005-7-7 20:23:00)
 
有谁能告诉我这个支持MYSQL的VC环境如何设置???
急急急,请大侠指教!!! ( ddvlwy 发表于 2005-3-24 18:14:00)
 
Compiling...
Database.cpp
f:\mysql\include\mysql_com.h(180) : error C2065: 'SOCKET' : undeclared identifier
fe:\vc\vc98\include\winsock.h(51) : error error C2501: 'SOCKET' : missing storage-class or type
.........
 specifiers
e:\vc\vc98\include\winsock.h(707) : error C2146: g:\documents and settings\ddv\桌面\《mysql数据库接口的vc实现与应用》配套代码\database.cpp(187) : error C2440: 'initializing' : cannot convert from 'const char *' to 'char *'
        Conversion loses qualifiers
Error executing cl.exe.

Database.exe - 59 error(s), 19 warning(s)
( ddvlwy 发表于 2005-3-24 14:43:00)
 
编译错误的朋友看过来:如果编译提示找不到mysql.h.请你下载mysql 的源代码.因为是免费的,所以到哪都能找到,代码的版本跟你机器上装的MYSQL 版本不一致也不要紧,我机器上就不一致,但能正常编译.下载解压缩释放到你想要的目录下.然后是:在VC开发环境中,点菜单:TOOS,然后OPTIONS,然后DIRECTORIES,然后在INCLUDE FILES中包含进你刚才下载的MYSQL的源代码.当然libmysql.lib也要在SETTING中设置好.然后编译,就成功了!跟本不会报任何错误的.另外在WORKSPACE中的FILEVIEW的EXTERNAL DEPENDENCIES中肯定会自动出现4个文件,这些文件正好是你的程序中要用到的4个MYSQL提供的头文件.这可不是VC提供的哦,这是MYSQL开发小组提供的.么样,免费的就是好吧!如果有什么问题,请提问! ( ckp 发表于 2004-11-26 13:15:00)
 
.......................................................

--------------------next---------------------

阅读(205) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~