C/C++連接MySql數據庫


本文對如何使用MySql的API連接MySql數據庫,開發環境為VS2008.

 

一、VS2008工程設置工作

首先,建立一個windows應用程序的工程,將C/C++->預處理器->預處理器定義下的_WINDOWS改為_CONSOLE,

image

將連接器->系統->子系統 選擇為控制台。

image

由於我們要使用Mysql的API,並且我們機子上肯定安裝了Mysql數據庫,所以我們要將工程的頭文件路徑指向Mysql安裝目錄的同文件mysql.h所在的位置,將連接庫路徑指向libmysql.lib所在的路徑,

在我的機子上,Mysql 的安裝路徑為:C:\Program Files\MySQL\MySQL Server 5.1

image

image

我們需要把VS2008的工程中的頭文件路徑和連接庫路徑指向上面的兩個地方:

 

 

將x項目屬性頁的C/C++->常規->附加包含目錄指向:C:\Program Files\MySQL\MySQL Server 5.1\include

image

 

將項目屬性頁的鏈接器->常規->附加庫目錄指向:C:\Program Files\MySQL\MySQL Server 5.1\lib\opt.

image

將鏈接器->輸入->附加依賴項中添加libmysql.lib。

image

如果不設置鏈接器->輸入->附加依賴項中添加libmysql.lib,那么會出現如下的錯誤:

1>------ 已啟動全部重新生成: 項目: MySql-Connect, 配置: Debug Win32 ------
1>正在刪除項目“MySql-Connect”(配置“Debug|Win32”)的中間文件和輸出文件
1>正在編譯...
1>MySql_Connect.cpp
1>x:\編程練習\c-c++\c\mysql_connect.cpp(35) : warning C4996: 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>        d:\program files\microsoft visual studio 9.0\vc\include\stdio.h(306) : 參見“scanf”的聲明
1>x:\編程練習\c-c++\c\mysql_connect.cpp(72) : warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>        d:\program files\microsoft visual studio 9.0\vc\include\stdio.h(366) : 參見“sprintf”的聲明
1>x:\編程練習\c-c++\c\mysql_connect.cpp(86) : warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>        d:\program files\microsoft visual studio 9.0\vc\include\stdio.h(366) : 參見“sprintf”的聲明
1>正在編譯資源清單...
1>Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1
1>Copyright (C) Microsoft Corporation.  All rights reserved.
1>正在鏈接...
1>LINK : 沒有找到 d:\我的文檔\Visual Studio 2008\Projects\MySql-Connect\Debug\MySql-Connect.exe 或上一個增量鏈接沒有生成它;正在執行完全鏈接
1>MySql_Connect.obj : error LNK2019: 無法解析的外部符號 _mysql_close@4,該符號在函數 _main 中被引用
1>MySql_Connect.obj : error LNK2019: 無法解析的外部符號 _mysql_free_result@4,該符號在函數 _main 中被引用
1>MySql_Connect.obj : error LNK2019: 無法解析的外部符號 _mysql_num_fields@4,該符號在函數 _main 中被引用
1>MySql_Connect.obj : error LNK2019: 無法解析的外部符號 _mysql_fetch_row@4,該符號在函數 _main 中被引用
1>MySql_Connect.obj : error LNK2019: 無法解析的外部符號 _mysql_store_result@4,該符號在函數 _main 中被引用
1>MySql_Connect.obj : error LNK2019: 無法解析的外部符號 _mysql_error@4,該符號在函數 _main 中被引用
1>MySql_Connect.obj : error LNK2019: 無法解析的外部符號 _mysql_real_query@12,該符號在函數 _main 中被引用
1>MySql_Connect.obj : error LNK2019: 無法解析的外部符號 _mysql_select_db@8,該符號在函數 _main 中被引用
1>MySql_Connect.obj : error LNK2019: 無法解析的外部符號 _mysql_real_connect@32,該符號在函數 _main 中被引用
1>MySql_Connect.obj : error LNK2019: 無法解析的外部符號 _mysql_init@4,該符號在函數 _main 中被引用
1>d:\我的文檔\Visual Studio 2008\Projects\MySql-Connect\Debug\MySql-Connect.exe : fatal error LNK1120: 10 個無法解析的外部命令
1>生成日志保存在“file://d:\我的文檔\Visual Studio 2008\Projects\MySql-Connect\MySql-Connect\Debug\BuildLog.htm”
1>MySql-Connect - 11 個錯誤,3 個警告
========== 全部重新生成: 成功 0 個,失敗 1 個,跳過 0 個 ==========

 如果即使設置鏈接器,但是上面的錯誤仍然存在,可能是有序操作系統的原因:

由於系統是32位或者64位的不同,編譯時會引起如下錯誤:

無法解析的外部符號 _mysql_real_connect, 無法解析的外部符號 _mysql_query,無法解析的外部符號 _mysql_init;

對於32位只要按照上述文章即可。

對於64位,有兩種方法解決上述錯誤:

方法一:由於VS建立的項目默認為WIN32 項目,需將平台改為64。設置如下:

(1)項目—>屬性—>配置屬性—>配置管理器—>活動解決方案平台,下拉選新建,出現一個新的對號框,在鍵入選擇新平台中選擇X64,如下圖所示:

 配置結果為:

(2)不是將C:/ProgramFiles/MySQL/MySQL Server 5.7/lib(安裝MySql下的lib文件夾)中的libmysql.dll拷到項目下的Debug文件夾中,而是拷到項目下x64/Debug中(或者C:/Windows/System32中)。完畢。。

方法二:要包含32位的lib文件和dll文件。

32/64位MySql(lib、dll)資源:http://download.csdn.net/detail/u010439291/8453041

(1)首先下載32位的lib文件和dll文件。

(2)需要將32位的lib文件拷到C:/Program Files/MySQL/MySQL Server 5.7/lib(安裝Mysql下的lib文件夾),拷貝之前需要將原來的libmysql.lib更名。也可以不改變原來的lib文件名稱,而將32位的libmysql.lib 改為libmysql32.lib 同時在:

項目—>屬性—>連接器—>輸入—>附加依賴項:添加libmysql32.lib(名稱和之前保持一致)。編譯通過之后,運行還要將32位的libmysql.dll放在工程目錄Debug文件夾中或者System32下。

二、連接Mysql和從MySql中取出數據的API介紹

2.1 mysql_real_connect()

2.1.1 函數原型:

MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned int client_flag)

2.1.2 參數說明:

• 第一個參數應該是一個現存MYSQL結構的地址。在調用mysql_real_connect()之前,你必須調用mysql_init()初始化MYSQL結構。見下面的例子。

• host值可以是一個主機名或一個IP地址。如果host是NULL或字符串"localhost",假定是到本地主機的一個連接。如果OS支持套接字(Unix)或命名管道(Win32),使用他們而不是TCP/IP與服務器連接。

• user參數包含用戶的MySQL登錄ID。如果user是NULL,假定是當前用戶。在Unix下,它是當前登錄名。在Windows ODBC下,必須明確地指定當前用戶名字。見16.4 怎樣填寫ODBC管理程序中各種域。

• passwd參數為user包含口令。如果passwd是NULL,只有在user表中對於有一個空白口令字段的用戶的條目將被檢查一個匹配。這允許數據庫主管設置MySQL權限,使用戶獲得不同的口令,取決於他們是否已經指定一個口令。注意:不要試圖在調用mysql_real_connect()前加密口令;口令加密自動被客戶API處理。

• db是數據庫名。如果db不是NULL,連接將缺省數據庫設置為這個值。

• 如果port不是0,值對於TCP/IP連接將用作端口號。注意host參數決定連接的類型。

• 如果unix_socket不是NULL,字符串指定套接字或應該被使用的命名管道。注意host參數決定連接的類型。

• client_flag值通常是0,但是在很特殊的情況下可以被設置為下列標志的組合:

標志名字 意味着的標志

CLIENT_FOUND_ROWS 返回找到的(匹配的)行數,不是受到影響的行數。

CLIENT_NO_SCHEMA 不允許db_name.tbl_name.col_name語法。這是為了ODBC;如果你使用該語法,導致語法分析器產生一個錯誤,它是為在一些ODBC程序捕捉錯誤是有用的。

CLIENT_COMPRESS 使用壓縮協議。

CLIENT_ODBC 客戶是一個ODBC客戶。這使mysqld變得對ODBC更友好。

2.1.3 返回值

如果連接成功,一個 MYSQL*連接句柄。如果連接失敗,NULL。對一個成功的連接,返回值與第一個參數值相同,除非你傳遞NULL給該參數。

2.1.4 錯誤

CR_CONN_HOST_ERROR

不能連接MySQL服務器。

CR_CONNECTION_ERROR

不能連接本地MySQL服務器。

CR_IPSOCK_ERROR

不能創建一個IP套接字。

CR_OUT_OF_MEMORY

內存溢出。

CR_SOCKET_CREATE_ERROR

不能創建一個Unix套接字。

CR_UNKNOWN_HOST

不能找到主機名的IP地址。

CR_VERSION_ERROR

由於試圖使用一個不同協議版本的一個客戶庫與一個服務器連接導致的一個協議失配。如果你使用一個非常老的客戶庫連接一個沒有使用--old-protocol選項啟動的新服務器,這就能發生。

CR_NAMEDPIPEOPEN_ERROR;

不能在 Win32 上創建一個命名管道。

CR_NAMEDPIPEWAIT_ERROR;

不能在 Win32 上等待一個命名管道。

CR_NAMEDPIPESETSTATE_ERROR;

不能在 Win32 上得到一個管道處理器。

2.2  mysql_select_db()

2.2.1 函數原型

int mysql_select_db(MYSQL *mysql, const char *db)

2.2.2 參數說明

使得由db指定的數據庫成為 在由mysql指定的連接上的缺省(當前)數據庫。在隨后的查詢中,這個數據庫對於不包括一個顯式的數據庫指定符的表的引用是缺省數據庫。

除非連接的用戶能被認證允許使用數據庫,否則mysql_select_db()失敗。

2.2.3 返回值

成功,零。如果發生一個錯誤,非零。

2.2.4  錯誤

CR_COMMANDS_OUT_OF_SYNC

命令以一個不適當的次序被執行。

CR_SERVER_GONE_ERROR

MySQL服務器關閉了。

CR_SERVER_LOST

對服務器的連接在查詢期間失去。

CR_UNKNOWN_ERROR

發生一個未知的錯誤。

 

2.3 mysql_real_query

2.3.1 函數原型

int mysql_real_query(MYSQL *mysql, const char *query, unsigned int length)

2.3.2 參數說明

執行由query指向的SQL查詢,它應該是一個length個字節的字符串。查詢必須由一個單個的SQL語句組成。你不應該在語句后增加一個終止的分號(“;”)或\g。

對於包含二進制數據的查詢,你必須使用mysql_real_query()而不是mysql_query(),因為二進制代碼數據可能包含“\0”字符,而且,mysql_real_query()比mysql_query()更快,因為它對查詢字符串調用strlen()。

2.3.3 返回值

如果查詢成功,零。如果發生一個錯誤,非零。

2.3.4  錯誤

CR_COMMANDS_OUT_OF_SYNC

命令以一個不適當的次序被執行。

CR_SERVER_GONE_ERROR

MySQL服務器關閉了。

CR_SERVER_LOST

對服務器的連接在查詢期間失去。

CR_UNKNOWN_ERROR

發生一個未知的錯誤。

 

2.4 mysql_store_result

2.4.1 函數原型

MYSQL_RES *mysql_store_result(MYSQL *mysql)

2.4.2 返回值

A MYSQL_RES result structure with the results. NULL (0) if an error occurred.

2.5  mysql_fetch_row()

Description

Retrieves the next row of a result set. When used after mysql_store_result(), mysql_fetch_row() returns NULL when there are no more rows to retrieve. When used after mysql_use_result(), mysql_fetch_row() returns NULL when there are no more rows to retrieve or if an error occurred.

The number of values in the row is given by mysql_num_fields(result). If row holds the return value from a call to mysql_fetch_row(), pointers to the values are accessed as row[0] to row[mysql_num_fields(result)-1]. NULL values in the row are indicated by NULL pointers.

The lengths of the field values in the row may be obtained by calling mysql_fetch_lengths(). Empty fields and fields containing NULL both have length 0; you can distinguish these by checking the pointer for the field value. If the pointer is NULL, the field is NULL; otherwise, the field is empty.

Return Values

A MYSQL_ROW structure for the next row. NULL if there are no more rows to retrieve or if an error occurred.

Errors

Note that error is not reset between calls to mysql_fetch_row()

參考資料:http://dev.mysql.com/doc/refman/5.6/en/index.html

 

三、利用Mysql庫提供的API編寫連接Mysql和從Mysql中取出數據的代碼

#include <windows.h>
#include "stdio.h"
#include "winsock.h" 
#include "mysql.h" 
 
int main()
{
    MYSQL * con; //= mysql_init((MYSQL*) 0); 
    MYSQL_RES *res;
    MYSQL_ROW row;
     
     
    char tmp[400];
     
    //database configuartion
    char dbuser[30]="root"; 
    char dbpasswd[30]="apple";
    char dbip[30]="localhost";
    char dbname[50]="excel";
    char tablename[50]="test";
    char *query=NULL;
     
     
    int x;
    int y;
    int rt;//return value
    unsigned int t;
     
    int count = 0;
     
     
    printf("input x,y\n");
    scanf("%d,%d",&x,&y);
    fflush(stdin);
    printf("input over\n");
    con = mysql_init((MYSQL*) 0); 
     
     
    if ( con !=NULL && mysql_real_connect(con,dbip,dbuser,dbpasswd,dbname,3306/*TCP IP端口*/,NULL/*Unix Socket 連接類型*/,0/*運行成ODBC數據庫標志*/) 
    { 
        if (!mysql_select_db(con,dbname)) 
        { 
            printf("Select successfully the database!\n"); 
            
            con ->reconnect = 1; 
            
            query = "set names \'GBK\'";
            //mysql_query(con,"set names \'GBK\'"); 
            
            rt=mysql_real_query(con,query,strlen(query));
            if (rt)
            {
                printf("Error making query: %s !!!\n",mysql_error(con));
            }
            else
            {
                printf("query %s succeed!\n",query);
            }
        
        }
    }
    else
    {
        MessageBoxA(NULL,"Unable to connect the database,check your configuration!","",NULL);
     
    }
 
    //sprintf(tmp,"update %s set 商品=\'%s\',賣出=%d,成交=%d,漲跌=%d,買進=%d,總量=%d,漲幅=%f,時間=\'%s\' where  %s",tablename,goods,sold,deal,fluctuate,buy,total,delta,time,UpdateCon);
    sprintf(tmp,"insert into %s values(%s,%d,%d)",tablename,"null",x,y); //注意如何向具有自增字段的數據庫中插入記錄
    //MessageBoxA(NULL,tmp,tmp,MB_OK);
    //mysql_query(con,tmp);
    
    rt=mysql_real_query(con,tmp,strlen(tmp));
    if (rt)
    {
        printf("Error making query: %s !!!\n",mysql_error(con));
    }
    else
    {
        printf("%s executed!!!\n",tmp);
    }
    
    sprintf(tmp,"select * from %s",tablename);
    
    rt=mysql_real_query(con,tmp,strlen(tmp));
    if (rt)
    {
        printf("Error making query: %s !!!\n",mysql_error(con));
    } 
    else
    {
        printf("%s executed!!!\n",tmp);
    }
    
    res = mysql_store_result(con);//將結果保存在res結構體中
    
    while(row = mysql_fetch_row(res))  
    {  
        /** 
        * MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *result); 
        * 檢索行 
        */  
        
        for(t=0;t<mysql_num_fields(res);t++)  
        {  
            printf("%s  ",row[t]);  
        }  
        printf(".............\n");  
        count ++;
    }  
    printf("number of rows %d\n",count);
    printf("mysql_free_result...\n");  
    mysql_free_result(res);  
    
    mysql_close(con);
    return 0;

}

四、運行結果

image

 

五、數據庫腳本

/*
Navicat MySQL Data Transfer

Source Server         : localhost
Source Server Version : 50141
Source Host           : localhost:3306
Source Database       : excel

Target Server Type    : MYSQL
Target Server Version : 50141
File Encoding         : 65001

Date: 2011-09-23 10:41:43
*/
 
 

  SET FOREIGN_KEY_CHECKS=0;
  -- ----------------------------
  -- Table structure for `test`
  -- ----------------------------
  DROP TABLE IF EXISTS `test`;
  CREATE TABLE `test` (
    `x` bigint(4) NOT NULL AUTO_INCREMENT,
    `y` int(4) DEFAULT NULL,
    `z` int(4) DEFAULT NULL,
    PRIMARY KEY (`x`)
  ) ENGINE=InnoDB AUTO_INCREMENT=118 DEFAULT CHARSET=latin1;
   
  -- ----------------------------
  -- Records of test
  -- ----------------------------
  INSERT INTO `test` VALUES ('95', '12432', '4334');
  INSERT INTO `test` VALUES ('96', '213', '321');
  INSERT INTO `test` VALUES ('97', '213', '213');
  INSERT INTO `test` VALUES ('98', '123', '231');
  INSERT INTO `test` VALUES ('99', '321', '231');
  INSERT INTO `test` VALUES ('100', '123', '32132');
  INSERT INTO `test` VALUES ('101', '777', '32213');
  INSERT INTO `test` VALUES ('102', '123', '213');
  INSERT INTO `test` VALUES ('103', '21', '321');
  INSERT INTO `test` VALUES ('104', '324', '432');
  INSERT INTO `test` VALUES ('105', '132', '231');
  INSERT INTO `test` VALUES ('106', '324', '342');
  INSERT INTO `test` VALUES ('107', '23', '23');
  INSERT INTO `test` VALUES ('108', '12', '21');
  INSERT INTO `test` VALUES ('109', '231', '321');
  INSERT INTO `test` VALUES ('110', '123', '231');
  INSERT INTO `test` VALUES ('111', '123', '231');
  INSERT INTO `test` VALUES ('112', '123', '123');
  INSERT INTO `test` VALUES ('113', '312', '231');
  INSERT INTO `test` VALUES ('114', '312', '321');
  INSERT INTO `test` VALUES ('115', '23', '3');
  INSERT INTO `test` VALUES ('116', '213', '312');
  INSERT INTO `test` VALUES ('117', '2', '3');
   
  -- ----------------------------
  -- Table structure for `xqdata`
  -- ----------------------------
  DROP TABLE IF EXISTS `xqdata`;
  CREATE TABLE `xqdata` (
    `代碼` varchar(20) NOT NULL DEFAULT '',
    `商品` varchar(20) CHARACTER SET utf8 DEFAULT NULL,
    `賣出` bigint(20) DEFAULT NULL,
    `成交` bigint(20) DEFAULT NULL,
    `漲跌` bigint(20) DEFAULT NULL,
    `買進` bigint(20) DEFAULT NULL,
    `總量` bigint(20) DEFAULT NULL,
    `漲幅` double DEFAULT NULL,
    `時間` time DEFAULT NULL,
    PRIMARY KEY (`代碼`)
  ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
   
  -- ----------------------------
  -- Records of xqdata
  -- ----------------------------
  INSERT INTO `xqdata` VALUES ('FITX*1', '商品', '34', '43', '23', '34', '0', '1.4', '13:23:08');

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM