免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3324 | 回复: 5
打印 上一主题 下一主题

Linux(Unix)下MySQL数据库访问接口程序MCI (MySQL Call Interface) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-08-31 22:10 |只看该作者 |倒序浏览
郑重声明:本MCI程序已经过严格的,长时间的反复测试和使用!
可支持对char,varchar,varchar2,int,float等类型数据进行各种select,update,insert操作
欢迎C++高手,MySQL来指点

本接口程序用C++完成,尤其适合server端使用,可通行于Linux/Unix/Windows平台
包括:mci.h mci.cpp 以及测试用例test.h test.cpp和一个makefile文件,可直接在RedHat上编译运行
本接口功能相信可满足大部分朋友的需要,你只需在你的程序里面包含这两个文件即可
(当然相应的makefile文件也需修改)
作者:欧昕 中国-成都 欢迎大家改进之,让其功能更加强大,我的联系QQ:30991118,欢迎骚扰...
[mci.h]:

  1. #ifndef  _MCI_H_
  2. #define  _MCI_H_
  3. #include <iostream>
  4. #include <pthread.h>
  5. #include <time.h>
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <memory.h>
  9. #include "/usr/local/mysql/include/mysql.h"
  10. const unsigned int MAX_FIELD_LEN = 1024*1;
  11. class MCIException
  12. {
  13. public:
  14.      int         ErrNo;
  15.      char        ErrInfo[256];
  16.      MCIException(const char *errinfo,int errno);
  17.         char *getErrInfo();
  18.         int   getErrNo(){return ErrNo;};
  19.         //自定义错误类型
  20.         //1    不支持的字段类型
  21.         //2    字段越界
  22.         //3    字段不存在
  23.         //MySQL内部错误类型
  24.         //2002 Can't connect to local MySQL server through socket
  25.         //2003 Can't connect to MySQL server
  26.         //2013 Lost connection to MySQL server during query
  27.         //1045 Access denied for user
  28. };

  29. class MCIDatabase
  30. {
  31.         public:
  32.         char DBIP[20];   //数据库IP地址
  33.         char User[10];         //用户名
  34.         char Pwd[10];         //密码
  35.         char DBName[20]; //数据库名
  36.         MYSQL *mysql;
  37.         public:
  38.                 MCIDatabase();
  39.                 MYSQL* getMySQL(){return mysql;};
  40.                 void setLogin(const char* dbip,const char* usr, const char* pwd, const char* dbname) ;
  41.                 int  connect();
  42.                 void disConnect();
  43. };

  44. class MCIField
  45. {
  46.         public:
  47.         friend class MCIQuery;
  48.         MCIQuery*        pParentQuery;                //指向该Field所属于的Query
  49.         char             FieldName[30];         //字段名称(目前支持30长度)
  50.         char                       StrBuf[255];                //用于保存转换为字符串后的值
  51.         unsigned char*         DataBuf;                        //预绑定缓冲区
  52.         enum_field_types FieldType;                        //MySQL内部数据类型
  53.         unsigned int         FieldLength;                //数据长度
  54.         public:
  55.                 MCIField();                                       
  56.                 ~MCIField();
  57.                 void setFieldName(const char* s);
  58.                 void setFieldType(enum_field_types n);
  59.                 void setFieldLength(unsigned int n);
  60.                
  61.                 char* getFieldName();
  62.                 char* getStrBuf();
  63.                 enum_field_types getFieldType();
  64.                 unsigned int getFieldLength();
  65.                
  66.                 MCIQuery* getParentQuery();
  67.                 void setParentQuery(MCIQuery* pQry);
  68.         static void  trimLeft(char* str);
  69.         static void  trimRight(char* str);
  70.         static char* allTrim(char* str);
  71.                 char*        asString();
  72.                 int          asInteger();
  73.                 float        asFloat();
  74.                 char         asChar(int pos = 0);
  75.                
  76. };

  77. class MCIQuery
  78. {
  79.         public:
  80.         MCIDatabase* pDB;
  81.         MYSQL_RES*   pRes;
  82.        
  83.         int          FieldNum;       //字段个数               
  84.         MYSQL_FIELD* pFields;             //得到的字段信息         
  85.     MCIField*    pMCIFieldList;  //在内部保存的所有字段信息
  86.                                     
  87.         MYSQL_ROW    Row;
  88.         int          RowNum;
  89.         char         SqlStr[1024*3];
  90.         int              CurrRow;
  91.        
  92.         /*
  93.         //检查超时用
  94.         int         ThreadExist;
  95.         int         ThreadMode;
  96.         pthread_t    QryID;
  97.         int  ErrNo;
  98.         char ErrInfo[256];
  99.         */
  100.        
  101.         public:
  102.                 MCIQuery();
  103.                 void setDB(MCIDatabase *dblink);
  104.                 ~MCIQuery();
  105.                 void  setSql(char* sqlstr);
  106.             void  open();                   //执行select型SQL语句
  107.             int   getFieldsDef();           //获得字段信息,并为字段分配取值的缓冲区
  108.             int   getRecordCount();                        //返回查询到的符合条件的记录的条数
  109.             int   next();                        //移动到下一个记录,同时获取字段值
  110.             MCIField* field(int i);         //取相应字段值
  111.             MCIField* fieldByName(const char* s);
  112.             int   exec();                                //执行insert,update型SQL语句,返回被此语句影响的记录条数
  113.             void  close();                                        //关闭一个Query,为下次执行做准备
  114.            
  115.             /*
  116.             //检查超时用
  117.             int runSql();
  118.             static void* QryThread(void* arg);
  119.             */
  120. };
  121. #endif
  122. [color=Red][b][mci.cpp]:[/b][/color]
  123. #include "mci.h"

  124. MCIException::MCIException(const char *errinfo,int errno)
  125. {
  126.         memset(ErrInfo,0,sizeof(ErrInfo));
  127.         strncpy(ErrInfo,errinfo,sizeof(ErrInfo)-1);
  128.         ErrNo = errno;
  129. }

  130. char* MCIException::getErrInfo()
  131. {
  132.         return ErrInfo;
  133. }

  134. MCIDatabase::MCIDatabase()
  135. {
  136.         memset(DBName,0,sizeof(DBName));
  137.         memset(User,0,sizeof(User));
  138.         memset(Pwd,0,sizeof(Pwd));
  139.         mysql = NULL;
  140. }

  141. //设置登陆信息
  142. void MCIDatabase::setLogin(const char* dbip,const char* usr, const char* pwd,const char* dbname)
  143. {
  144.         memset(DBIP,0,sizeof(DBIP));
  145.         strcpy(DBIP,dbip);
  146.         memset(User,0,sizeof(User));
  147.         strcpy(User,usr);
  148.         memset(Pwd,0,sizeof(Pwd));
  149.         strcpy(Pwd,pwd);
  150.         memset(DBName,0,sizeof(DBName));
  151.         strcpy(DBName,dbname);
  152. }

  153. //连接到数据库
  154. int MCIDatabase::connect()
  155. {
  156.         mysql = NULL;
  157.         mysql = mysql_init(NULL);
  158.         if (mysql == NULL)
  159.         {
  160.                 char errinfo[256];
  161.                 memset(errinfo,0,sizeof(errinfo));
  162.                 sprintf(errinfo, "%s\n",mysql_error(mysql));
  163.                 int errno = mysql_errno(mysql);
  164.                 throw MCIException(errinfo,errno);
  165.                 return 0;
  166.         }
  167.         unsigned int timeout = 3;
  168.         mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT,(char *) &timeout);//超时
  169.         //mysql_options(mysql, MYSQL_OPT_COMPRESS,NULL);//与服务器的通信采用压缩协议
  170.         //建立连接
  171.         //DBIP如果设为"localhost"或NULL,则表示使用socket连接本地主机
  172.         //DBIP如果设为字符串或IP数字形式的主机名,则表示使用TCP/IP连接本地主机
  173.         if(mysql_real_connect(mysql,DBIP,User,Pwd,DBName,0,NULL,CLIENT_INTERACTIVE) == NULL)
  174.         {
  175.                 char errinfo[256];
  176.                 memset(errinfo,0,sizeof(errinfo));
  177.                 sprintf(errinfo, "%s\n",mysql_error(mysql));
  178.                 int errno = mysql_errno(mysql);
  179.                 throw MCIException(errinfo,errno);
  180.                 return 0;
  181.         }
  182.         return 1;
  183. }

  184. //关闭连接
  185. void MCIDatabase::disConnect()
  186. {
  187.         if (mysql != NULL) mysql_close(mysql);
  188. }

  189. MCIField::MCIField()
  190. {
  191.         pParentQuery = NULL;
  192.         memset(FieldName,0,sizeof(FieldName));
  193.         memset(StrBuf,0,sizeof(StrBuf));
  194.         DataBuf = NULL;
  195.         FieldType = FIELD_TYPE_STRING;
  196. }

  197. MCIField::~MCIField()
  198. {
  199.         if (DataBuf != NULL)
  200.         {
  201.                 delete[] DataBuf;
  202.                 DataBuf = NULL;
  203.         }
  204. }

  205. MCIQuery* MCIField::getParentQuery()
  206. {
  207.         return pParentQuery;
  208. }

  209. void MCIField::setParentQuery(MCIQuery* pQry)
  210. {
  211.         pParentQuery = pQry;
  212. }

  213. char* MCIField::getFieldName()
  214. {
  215.         return FieldName;
  216. }

  217. char* MCIField::getStrBuf()
  218. {
  219.         return StrBuf;
  220. }

  221. enum_field_types MCIField::getFieldType()
  222. {
  223.         return FieldType;
  224. }

  225. unsigned int MCIField::getFieldLength()
  226. {
  227.         return FieldLength;
  228. }
  229.                
  230. void MCIField::setFieldName(const char* s)
  231. {
  232.         memset(FieldName,0,sizeof(FieldName));
  233.         strncpy(FieldName,s,sizeof(FieldName)-1);
  234. }

  235. void MCIField::setFieldType(enum_field_types n)
  236. {
  237.         FieldType = n;
  238. }

  239. void MCIField::setFieldLength(unsigned int n)
  240. {
  241.         FieldLength = n;
  242. }
  243.                
  244. MCIQuery::MCIQuery()
  245. {
  246.         pDB = NULL;
  247.         pRes = NULL;
  248.         FieldNum = 0;
  249.         pFields = NULL;             
  250.     pMCIFieldList = NULL;
  251.         RowNum = 0;
  252.         memset(SqlStr,0,sizeof(SqlStr));
  253.         CurrRow = 0;
  254.        
  255.         /*
  256.         //检查超时用
  257.         ThreadExist = 0;
  258.         ThreadMode = 0;
  259.         QryID = 0;
  260.         ErrNo = 0;
  261.         memset(ErrInfo,0,sizeof(ErrInfo));
  262.         */
  263. }

  264. //确定Qry指向的DataBase
  265. void MCIQuery::setDB(MCIDatabase *dblink)
  266. {
  267.         pDB = dblink;
  268. }

  269. MCIQuery::~MCIQuery()
  270. {
  271.         if(pRes != NULL)
  272.         {
  273.                 mysql_free_result(pRes);
  274.                 pRes = NULL;
  275.                
  276.         }
  277.         if(pMCIFieldList != NULL)
  278.         {
  279.                 delete[] pMCIFieldList;
  280.                 pMCIFieldList = NULL;
  281.         }
  282.         pFields = NULL;
  283. }

  284. //设置SQL语句
  285. void MCIQuery::setSql(char* sqlstr)
  286. {
  287.         memset(SqlStr,0,sizeof(SqlStr));
  288.         strcpy(SqlStr,sqlstr);
  289. }

  290. int MCIQuery::getRecordCount()
  291. {
  292.         return RowNum;
  293. }

  294. //获得字段信息,并为字段分配取值的缓冲区
  295. int MCIQuery::getFieldsDef()
  296. {
  297.         pRes = mysql_store_result(pDB->getMySQL()); //获取结果集
  298.         pFields =  mysql_fetch_fields(pRes);                 //获取MySQL字段信息
  299.         FieldNum = mysql_num_fields(pRes);               //字段个数
  300.         if (FieldNum > 0)
  301.         {
  302.                 pMCIFieldList = new MCIField[FieldNum];//建立自己的字段信息
  303.                 MCIField *pCurrField = NULL;
  304.                 for(int i = 0; i < FieldNum; i ++)
  305.                 {
  306.                         pCurrField = &pMCIFieldList[i];
  307.                         //设置此字段名称-类型-字段宽度
  308.                         pCurrField->setParentQuery(this);
  309.                         pCurrField->setFieldName(pFields[i].name);
  310.                         pCurrField->setFieldType(pFields[i].type);
  311.                         pCurrField->setFieldLength(pFields[i].length);
  312.                         if (pCurrField->getFieldLength() > MAX_FIELD_LEN)
  313.                       {
  314.                               //fprintf(stdout,"field:[%s]'s Length:[%d] More Than 1024\n",pCurrField->FieldName,pCurrField->FieldLength);fflush(stdout);
  315.                               pCurrField->setFieldLength(MAX_FIELD_LEN);
  316.                       }
  317.                       //建立供输出数据的缓冲区
  318.                 switch (pCurrField->getFieldType())
  319.                 {
  320.                                 case FIELD_TYPE_SET:
  321.                                         throw MCIException("Not Supported Data Type:[FIELD_TYPE_SET]",1);
  322.                                         break;
  323.                                 case FIELD_TYPE_ENUM:
  324.                                         throw MCIException("Not Supported Data Type:[FIELD_TYPE_ENUM]",1);
  325.                                         break;
  326.                                 case FIELD_TYPE_NULL:
  327.                                         throw MCIException("Not Supported Data Type:[FIELD_TYPE_NULL]",1);
  328.                                         break;
  329.                                 default:
  330.                                         pCurrField->DataBuf = new unsigned char[pCurrField->getFieldLength() + 1];
  331.                                         memset(pCurrField->DataBuf,0,sizeof(pCurrField->DataBuf));
  332.                         }
  333.                 }
  334.                 return 1;
  335.         }
  336.         return 0;
  337. }

  338. //移动到下一个记录,同时获取字段值
  339. int MCIQuery::next()
  340. {
  341.         if (RowNum <= 0) return 0;
  342.         if (CurrRow > RowNum) return 0;
  343.         //将当前行的各个列的值写入MCIField中
  344.         Row = mysql_fetch_row(pRes);
  345.         if (Row == NULL) return 0;
  346.         for(int i = 0; i < FieldNum; i ++)
  347.         {
  348.                 if( (Row[i] == NULL) || (pMCIFieldList[i].DataBuf == NULL) ) continue;
  349.                 memcpy(pMCIFieldList[i].DataBuf,Row[i],pMCIFieldList[i].getFieldLength());
  350.         }
  351.         CurrRow++;
  352.         return 1;
  353. }

  354. MCIField* MCIQuery::field(int i)
  355. {
  356.         if ( (i>=0) && (i<FieldNum) )
  357.                 return &pMCIFieldList[i];
  358.         else
  359.         {
  360.                 char errinfo[256];
  361.                 memset(errinfo,0,sizeof(errinfo));
  362.                 sprintf(errinfo, "Field:[%d] Out Of Bound",i);
  363.                 int errno = 2;
  364.                 throw MCIException(errinfo,errno);
  365.         }
  366. }

  367. MCIField* MCIQuery::fieldByName(const char* s)
  368. {
  369.         for(int i = 0;i < FieldNum;i++)
  370.         {
  371.                 if (strcmp(pMCIFieldList[i].getFieldName(),s) == 0)
  372.                         return &pMCIFieldList[i];
  373.         }
  374.         char errinfo[256];
  375.         memset(errinfo,0,sizeof(errinfo));
  376.         sprintf(errinfo, "Field:[%s] Not Find",s);
  377.         int errno = 3;
  378.         throw MCIException(errinfo,errno);
  379. }

  380. char* MCIField::allTrim(char *szString)
  381. {
  382.         trimLeft(szString);
  383.         trimRight(szString);
  384.         return szString;
  385. }

  386. void MCIField::trimLeft(char *str)
  387. {
  388.         int iStart=0;
  389.         int iLen, iCount;

  390.         iLen=strlen(str);
  391.         while( (str[iStart] == ' ') || (str[iStart] == '\t') ) iStart++;
  392.         for(iCount=iStart; iCount<=iLen; iCount++)
  393.         {
  394.                 str[iCount-iStart]=str[iCount];
  395.         }
  396. }

  397. void MCIField::trimRight(char *str)
  398. {
  399.         int len=strlen(str);
  400.         while(1)
  401.         {
  402.                 if (len<=0) break;
  403.                 if( (str[len-1]==' ') || (str[len-1]=='\t') )
  404.                 {
  405.             str[len-1]=0;
  406.             len--;
  407.         }
  408.                 else
  409.                     break;
  410.         }
  411. }

  412. char* MCIField::asString()
  413. {
  414.         static  char  nullstr[] = "";
  415.         char* p = (char *)DataBuf;
  416.         if ( (p == NULL) || (strlen(p) == 0) )
  417.         {
  418.                 return nullstr;
  419.         }
  420.         else
  421.                 return allTrim(p);
  422. }
  423. int MCIField::asInteger()
  424. {
  425.         return(atoi((char *)DataBuf));
  426. }
  427. float MCIField::asFloat()
  428. {
  429.         return(atof((char *)DataBuf));
  430. }

  431. char MCIField::asChar(int pos)
  432. {
  433.         return DataBuf[pos];
  434. }


  435. void MCIQuery::close()
  436. {
  437.         memset(SqlStr,0,sizeof(SqlStr));
  438.         if( (RowNum >0) && (pRes != NULL) )
  439.         {
  440.                 mysql_free_result(pRes);
  441.                 pRes = NULL;
  442.         }
  443.         if (FieldNum >0)
  444.         {
  445.                 for(int i = 0; i < FieldNum; i ++)
  446.                 {
  447.                         MCIField *pCurrField = &pMCIFieldList[i];
  448.                         delete[] pCurrField->DataBuf;
  449.                         pCurrField->DataBuf = NULL;
  450.                 }
  451.         }
  452.         if (pMCIFieldList != NULL)
  453.         {
  454.                 delete[] pMCIFieldList;
  455.                 pMCIFieldList = NULL;
  456.         }
  457.         if (pFields != NULL)
  458.         {
  459.                 //delete pFields;
  460.                 pFields = NULL;
  461.         }
  462.         FieldNum = 0;
  463.         RowNum = 0;
  464.         CurrRow = 0;
  465. }

  466. //执行需要返回结果集的SQL语句
  467. void MCIQuery::open()
  468. {
  469.         if (pDB->getMySQL() == NULL) return;
  470.         /*
  471.         //fprintf(stdout,"mysql_ping\n");fflush(stdout);
  472.         if (mysql_ping(pDB->getMySQL()) != 0)
  473.         {
  474.                 //fprintf(stdout,"mysql_ping failure\n");fflush(stdout);
  475.                 int ErrNo = mysql_errno(pDB->getMySQL());
  476.                 char ErrInfo[256];
  477.                 memset(ErrInfo,0,sizeof(ErrInfo));
  478.                 sprintf(ErrInfo, "%s\n",mysql_error(pDB->getMySQL()));
  479.                 throw MCIException(ErrInfo,ErrNo);
  480.         }
  481.         */
  482.         if (mysql_real_query(pDB->getMySQL(),SqlStr, strlen(SqlStr)) != 0)
  483.         {
  484.                 int ErrNo = mysql_errno(pDB->getMySQL());
  485.                 char ErrInfo[256];
  486.                 memset(ErrInfo,0,sizeof(ErrInfo));
  487.                 sprintf(ErrInfo, "%s\n",mysql_error(pDB->getMySQL()));
  488.                 throw MCIException(ErrInfo,ErrNo);
  489.         }

  490.         if (getFieldsDef() == 1)
  491.         {
  492.                 RowNum = mysql_num_rows(pRes);
  493.                 CurrRow = 0;
  494.         }
  495. }


  496. int MCIQuery::exec()
  497. {
  498.         if (pDB->getMySQL() == NULL) return 0;
  499.         /*
  500.         //fprintf(stdout,"mysql_ping\n");fflush(stdout);
  501.         if (mysql_ping(pDB->getMySQL()) != 0)
  502.         {
  503.                 //fprintf(stdout,"mysql_ping failure\n");fflush(stdout);
  504.                 int ErrNo = mysql_errno(pDB->getMySQL());
  505.                 char ErrInfo[256];
  506.                 memset(ErrInfo,0,sizeof(ErrInfo));
  507.                 sprintf(ErrInfo, "%s\n",mysql_error(pDB->getMySQL()));
  508.                 throw MCIException(ErrInfo,ErrNo);
  509.         }
  510.         */
  511.         //fprintf(stdout,"mysql_real_query\n");fflush(stdout);
  512.         if (mysql_real_query(pDB->getMySQL(),SqlStr, strlen(SqlStr)) != 0)
  513.         {
  514.                 //fprintf(stdout,"mysql_real_query failure\n");fflush(stdout);
  515.                 int ErrNo = mysql_errno(pDB->getMySQL());
  516.                 char ErrInfo[256];
  517.                 memset(ErrInfo,0,sizeof(ErrInfo));
  518.                 sprintf(ErrInfo, "%s\n",mysql_error(pDB->getMySQL()));
  519.                 throw MCIException(ErrInfo,ErrNo);
  520.         }
  521.         //fprintf(stdout,"mysql_real_query success\n");fflush(stdout);
  522.         return mysql_affected_rows(pDB->getMySQL());
  523. }
  524. [color=Red][b][test.h][/b][/color]//呵呵,test.h其实什么东西都没有,只是一个架子
  525. #ifndef  _TEST_H_
  526. #define  _TEST_H_
  527. #include "mci.h"
  528. #endif
  529. [color=Red][b][test.cpp][/b][/color]
  530. #include "test.h"

  531. MCIDatabase   MCIDB;

  532. int main(int argc,char* argv[])
  533. {
  534.         char SqlStr[256];
  535.         try                                
  536.         {               
  537.                 //连接数据库                  
  538.                 MCIDB.disConnect();            
  539.                 MCIDB.setLogin("192.168.0.111", "sa", "abc","atcdb");
  540.                 MCIDB.connect();
  541.                 fprintf(stdout,"connect db success\n");fflush(stdout);
  542.                 //创建一个Query
  543.                 MCIQuery* q = new MCIQuery();
  544.                 q->setDB(&MCIDB);               
  545.                 //执行select语句
  546.                 memset(SqlStr,0,sizeof(SqlStr));
  547.                 strcpy(SqlStr,"select * from table1");//假设有表table1
  548.                 q->close();
  549.                 q->setSql(SqlStr);
  550.                 q->open();
  551.                 while(q->next())
  552.                 {
  553.                         fprintf(stdout,"%s\n",q->fieldByName("field1")->asString());fflush(stdout);//假设该表有varchar2型字段field1
  554.                 }
  555.                 //执行update或insert语句
  556.                 q->close();
  557.                 sprintf(sql, "delete from table1");
  558.                 q->setSql(sql);
  559.                 q->exec();
  560.                 q->close();
  561.                 //释放内存
  562.                 delete q;
  563.                 MCIDB.disConnect();
  564.         }
  565.         catch(MCIException &oe)            
  566.         {                  
  567.                 fprintf(stdout,"%s\n",oe.getErrInfo());
  568.                 MCIDB.disConnect();
  569.                 delete q;
  570.         }
  571. }
复制代码

[makefile]
CC                         = g++
CFLAGS                 = -Wall
SQLHOME         = -L/usr/lib64 -lmysqlclient

all:test
test: mci.o test.o
        $(CC) -s -o test -m64 *.o  $(SQLHOME)

mci.o: mci.cpp mci.h
        $(CC) $(CFLAGS) -c mci.cpp
test.o: test.cpp test.h
        $(CC) $(CFLAGS) -c test.cpp

clean::
         rm -f *.o

[ 本帖最后由 oceania 于 2006-9-3 22:19 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2006-08-31 22:54 |只看该作者
原帖由 oceania 于 2006-8-31 22:10 发表
郑重声明:本MCI程序已经过严格的,长时间的反复测试和使用!
可支持对char,varchar,varchar2,int,float等类型数据进行各种select,update,insert操作
欢迎C++高手,MySQL来指点

本接 ...

>>
>>
>>赞一个!
>>
>>

论坛徽章:
0
3 [报告]
发表于 2006-09-01 13:22 |只看该作者
顶下

论坛徽章:
0
4 [报告]
发表于 2006-09-19 17:34 |只看该作者
好文章该置顶

论坛徽章:
0
5 [报告]
发表于 2006-10-06 07:48 |只看该作者
鼓励!提个建议,实现接口的时候,一定要反复斟酌,抽象出最普遍和常用的一些函数,比如connect, ExecuteSQL(char*),getRows等

论坛徽章:
0
6 [报告]
发表于 2006-10-13 16:23 |只看该作者
强烈感谢!!!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP