mysql學習筆記1【利用mysql connector/c 訪問數據庫】


2018-06-08


最近想學習一下mysql,看了一下書《MySQL必知必會》, 感覺書講的還不錯,也不是很厚,260頁,大略的翻完了,然后自己也下載了mysql安裝了,實際操作了一下,感覺書里面前2章內容略微陳舊了,

簡單的管理數據庫,查詢可以直接安裝mysql workbench,感覺界面挺不錯,也很好用。那個 mysql shell似乎可以甩在一邊不用了。
對着書大概了用了一些mysql 語句,對mysql有點認識后,打算用c語言來訪問mysql服務器,進行一些操作。找了一下,看見有一些庫給不同的語言用,來和mysql交互。比如c語言可以用 mysql connector/c 庫。

現在記錄一下我在windows系統下,利用visual stdudio 2015 ,用c語言 訪問mysql數據庫,進行了一個簡單查詢語句的整個過程。


工程代碼如下:

 1 #include <stdio.h>
 2 
 3 #include <mysql.h>
 4 
 5 #pragma comment(lib, "ws2_32.lib")
 6 #pragma comment(lib, "Secur32.lib")
 7 #pragma comment(lib, "mysqlclient.lib")
 8 //#pragma comment(lib, "libmysql.lib")  使用這個總是會報錯, lnk1107 文件無效或損壞,無法在0x348處讀取
 9 
10 #define LOG(...)  fprintf(stderr, __VA_ARGS__)
11 
12 int main(int argc, char* argv[])
13 {
14     MYSQL* pmysql = mysql_init(NULL);
15     if (pmysql == NULL)
16     {
17         LOG("初始化mysql庫失敗\n");
18         return -1;
19     }
20 
21     MYSQL* ret = mysql_real_connect(pmysql, "localhost","test","test*","world",0,NULL,0);
22     if (ret == NULL)
23     {
24         LOG("連接到數據庫 %s:%s 失敗\n","localhost","world");
25         return -1;
26     }
27 
28     int ret_query = mysql_query(pmysql,"SELECT * FROM world.city;");
29     if (ret_query == 0)
30     {
31         MYSQL_RES * my_result = mysql_store_result(pmysql);
32 
33         int num = mysql_num_fields(my_result);
34         int i;
35         MYSQL_ROW row;
36         while ((row = mysql_fetch_row(my_result)) != NULL)
37         {
38             for (i = 0; i < num; i++)
39             {
40                 printf("%s\t", row[i]);
41             }
42             printf("\n");
43         }
44 
45         // 釋放獲取的結果
46         mysql_free_result(my_result);
47     }
48 
49     mysql_close(pmysql);
50     mysql_library_end();
51     return 0;
52 }

 

完整的工程可以到我的github上下載      

https://github.com/fish404/mysql_learning 

 

 

編譯時候有幾個地方要注意:

1、需要指定mysql.h 所在的頭文件的路徑,vs 在項目屬性中設置。項目屬性頁 --》 c/c++ --》常規 --》附加包含目錄中指定,最好用雙引號將路徑包含起來,如我的路徑是 "C:\Program Files (x86)\MySQL\MySQL Connector C 6.1\include"。

2、需要指定 mysqlclient.lib 所在的庫路徑,注意這個路徑跟你的vs 的版本有關,比如我的是 vs 2015,連接的庫版本也要是2015編譯出來的,對應的connector lib目錄下 vs14目錄,路徑是 “C:\Program Files (x86)\MySQL\MySQL Connector C 6.1\lib\vs14”。

3、不要直接在屬性也中指定依賴的庫,否則連接的時候總是報錯,搜了一下不知道是什么原因,最后用代碼文件開頭 #pragma comment(lib, "mysqlclient.lib") 編譯通過。

4、還需要依賴 另外兩個庫 ws2_32.lib 和 Secur32.lib,跟上一點一樣指定。

5、vs 配置管理器中選擇x86,則也要安裝 mysql  connector/c 的x86版本,前面1,2包含的路徑也要是x86版本的路徑。x64版本的不知道為何,總是報錯。

6、連接靜態庫 mysqlclient.lib 可以運行,但是用動態庫libmysql.dll 總是失敗。暫時沒有深究原因。




參考文檔:
1、https://dev.mysql.com/doc/refman/5.6/en/c-api-function-overview.html    概述說明
2、https://dev.mysql.com/doc/refman/5.6/en/c-api-functions.html     各個函數詳細參數說明,返回值意義等
3、https://www.codeproject.com/Articles/34646/Accessing-MySQL-data-base-using-MySQL-C-API, 別人寫的一個示例,用c++包裝了。


下面一段是對參考文檔1 的翻譯,大概是講了使用的步驟,一些注意事項。

 

連接的庫
libmysqlclient 或者 libmysqld
 
mysql_library_init() 初始化mysql客戶庫 。這個函數不是線程安全,多線程情況下一定要先調用這個函數之后,再生成線程,調用其它庫函數。
 
mysql_init() 初始化一個連接處理器。 會間接調用mysql_library_init函數,非多線程環境下,可以省略上面這個函數。
 
mysql_real_connect() 連接到服務器
 
函數原型是 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 long client_flag)
 
mysql_close() 關閉到服務器的連接
 
mysql_library_end() 用完了mysql庫后需要釋放,不然有些內存會保持分配,讓一些工具軟件抱怨。
 
 
連接成功后,可以調用下面兩個函數來執行sql語句。
 
mysql_query() 期望查詢語句是null結尾。 每一次調用這個查詢后,接着調用mysql_store_result 或者 mysql_use_result來處理結果。
 
mysql_real_query() 如果字符串中有二進制的數據,必須使用這個函數。
 
sql語句有select語句,非select語句(如insert,update,delete)。對非select語句,
可以調用 mysql_affected_rows() 得到有多少行收到影響。
 
對select語句(包括select,show,describe,explain),你將獲取到選中的行作為結果集合。
 
有2種方式處理結果集合。
  • 一個是mysql_store_result(),這個函數一次性獲取所有的選中的行,保存到客戶處。這種方式用的比較多,因為你可以順序訪問所有的行,並且可以前后移動行,通過mysql_row_seek() 或者 mysql_data_seek() 來改變結果集合中的當前行位置。
還可以通過mysql_num_rows()知道一共有多少行返回了。
這個方式缺點是可能如果返回結果太多,內存可能不夠,而且等待時間可能較大。
  • 另一個是 mysql_use_result(),這個函數只是初始化獲取,但是實際上還沒有從服務器獲取任意一行數據。
 
上面任意一種方式,都可以調用mysql_fetch_row() 來訪問獲取的結果的一行。對第二種方式,該函數實際是從服務器獲取數據。
 
mysql_fetch_field() 可以用來獲取各個字段信息,通過在一行中連續調用。也可以通過mysql_fetch_field_direct() 指定字段號來獲取字段信息。mysql_field_seek() 可以改變當前字段游標位置。
 
mysql_fetch_fields() 可以一次獲取所有的字段信息。
 
mysql_fetch_lengths() 可以獲取每行的長度信息。
mysql_free_result() 用完結果后釋放內存。
關於mysql_store_result() 還有一點補充,如果這個函數返回成功,那么sql語句是select語句。如果失敗,進一步調用 mysql_field_count() 來判斷結果是否符合預期,如果這個函數返回0,說明sql語句不需要返回語句,以為着這是一個insert,update,
delete語句。如果不為0,則說明它期待返回數據,sql語句是select語句,並且失敗了。
 

 


免責聲明!

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



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