The MySQL C API程式設計例項
在網上找了一些MYSQL C API程式設計的文章,看了後覺得還是寫的不夠充分,根據自己經驗寫了這篇《The MySQL C API 程式設計例項》,希望對需要呼叫到MYSQL的C的API的朋友有所幫助,附例中的環境為RedHat
在這篇文章裡,我們將學會怎麼使用MySQL 的C APIs(Application Programming Interfaces 程式設計介面)。為了很好地瞭解這篇文章,您需要具備以下前提知識:
- C語言變數
- C語言函式
- C語言指標
簡介
C APIs包含在mysqlclient庫檔案當中與MySQL的原始碼一塊發行,用於連線到資料庫和執行資料庫查詢。有一些例子在MySQL原始碼的clients目錄裡。
MySQL C 變數型別
以下變數型別在MySQL的庫當中定義。我們需要這些變數是為了使用MySQL的函式。這些變數有詳細的解釋,但是這些解釋對於寫程式碼來說並不重要。
MYSQL
以下程式碼塊是用來連線資料庫的通訊過程,要連線MYSQL,必須建立MYSQL例項,通過mysql_init初始化方能開始進行連線,這個在後面會講到。
typedef struct st_mysql { NET net; /* Communication parameters */ gptr connector_fd; /* ConnectorFd for SSL */ char *host,*user,*passwd,*unix_socket, *server_version,*host_info,*info,*db; unsigned int port,client_flag,server_capabilities; unsigned int protocol_version; unsigned int field_count; unsigned int server_status; unsigned long thread_id; /* Id for connection in server */ my_ulonglong affected_rows; my_ulonglong insert_id; /* id if insert on table with NEXTNR */ my_ulonglong extra_info; /* Used by mysqlshow */ unsigned long packet_length; enum mysql_status status; MYSQL_FIELD *fields; MEM_ROOT field_alloc; my_bool free_me; /* If free in mysql_close */ my_bool reconnect; /* set to 1 if automatic reconnect */ struct st_mysql_options options; char scramble_buff[9]; struct charset_info_st *charset; unsigned int server_language; } MYSQL; |
MYSQL_RES
這個結構代表返回行的一個查詢的(SELECT
, SHOW
, DESCRIBE
, EXPLAIN
)的結果。返回的資料稱為“資料集”,用過資料庫的朋友應該對資料庫中查詢後得到的結果集不會陌生,在C的API裡對應的就是MYSQL_RES了,從資料庫讀取資料,最後就是從MYSQL_RES中讀取資料。
typedef struct st_mysql_res { my_ulonglong row_count; unsigned int field_count, current_field; MYSQL_FIELD *fields; MYSQL_DATA *data; MYSQL_ROWS *data_cursor; MEM_ROOT field_alloc; MYSQL_ROW row; /* If unbuffered read */ MYSQL_ROW current_row; /* buffer to current row */ unsigned long *lengths; /* column lengths of current row */ MYSQL *handle; /* for unbuffered reads */ my_bool eof; /* Used my mysql_fetch_row */ } MYSQL_RES; |
MYSQL_ROW
這是一個行資料的型別安全(type-safe)的表示。當前它實現為一個計數字節的字串陣列。(如果欄位值可能包含二進位制資料,你不能將這些視為空終止串,因為這樣的值可以在內部包含空位元組) 行通過呼叫mysql_fetch_row()
獲得。
typedef char **MYSQL_ROW; |
MYSQL_FIELD
這個結構包含欄位資訊,例如欄位名、型別和大小。其成員在下面更詳細地描述。你可以通過重複呼叫mysql_fetch_field()對每一列獲得MYSQL_FIELD結構。欄位值不是這個結構的部分;他們被包含在一個MYSQL_ROW結構中。
typedef struct st_mysql_field { char *name; /* Name of column */ char *table; /* Table of column if column was a field */ char *def; /* Default value (set by mysql_list_fields) */ enum enum_field_types type; /* Type of field. Se mysql_com.h for types */ unsigned int length; /* Width of column */ unsigned int max_length; /* Max width of selected set */ unsigned int flags; /* Div flags */ unsigned int decimals; /* Number of decimals in field */ } MYSQL_FIELD; |
my_ulonglong
typedef unsigned long my_ulonglong; |
該型別用於行編號和mysql_affected_rows()、mysql_num_rows()和mysql_insert_id()。這種型別提供0到1.84e19的一個範圍。在一些系統上,試圖列印型別my_ulonglong的值將不工作。為了列印出這樣的值,將它變換到unsigned long並且使用一個%lu列印格式。例如:
printf (Number of rows: %lu/n", (unsigned long) mysql_num_rows(result)); |
連線MySQL,查詢資料
現在假設MySQL已安裝, 使用者和資料表在資料庫被創造。以防有什麼不明問題的情況, 請參考www.mysql.com網站。
前面已經說過,MySQL的庫檔案在mysqlclient。因此在編譯MySQL程式的時候有必要加上-lmysqlclient編譯選項。MySQL的標頭檔案在/usr/include/mysql目錄下(根據Linux的發行版本的不同,這個目錄也有所不同),因此你的程式頭部看起來有點這個樣子:
|
MySQL的變數型別和函式都包含在這個標頭檔案當中
然後,我們需要建立連線資料庫的變數,可以簡單地這麼做:
|
在連線資料庫之前,我們要呼叫以下函式初始化這個變數:
|
然後,呼叫mysql_real_connect函式:
|
該函式被呼叫連線到資料庫。host是MySQL伺服器的主機名,user是登入的使用者名稱,passwd是登入密碼,db是要連線的資料庫,port是MySQL伺服器的TCP/IP埠,unix_socket是連線型別,clientflag是MySQL執行成ODBC資料庫的標記。在這篇文章當中該標記設成0,連線尋建立後,這個函式返回0。
現在可以連線資料庫,進行查詢了:
|
使用這個字串我們可以創立任何SQL查詢語句進行查詢。執行這個查詢的函式是:
|
mysql是我們前面用過的變數,q是SQL查詢語句,length是這個查詢語句的長度。如果查詢成功,函式返回0。
查詢之後,我們要到一個MYSQL_RES變數來使用查詢的結果。以下這行創立這個變數:
|
然後
res = mysql_store_result(&mysql); |
對客戶端而言,有兩種方法處理結果集合。一種方法是通過呼叫mysql_store_result()立刻檢索全部結果。該函式從伺服器獲得查詢返回的所有行,並將他們儲存在客戶端。第二種方法是對客戶通過呼叫mysql_use_result()初始化一個一行一行地結果集合的檢索。該函式初始化檢索,但是實際上不從伺服器獲得任何行。
在兩種情況中,你通過mysql_fetch_row()存取行。用mysql_store_result()、mysql_fetch_row()儲存取已經從伺服器被取出的行。用mysql_use_result()、mysql_fetch_row()實際上從伺服器檢索行。呼叫mysql_fetch_lengths()可獲得關於每行中資料值尺寸的資訊。
在你用完一個結果集合以後,呼叫mysql_free_result()釋放由它使用的記憶體。
兩種檢索機制是互補的。客戶程式應該選擇最適合他們的要求的途徑。在實踐中,客戶通常更願意使用mysql_store_result()。
該函式讀出查詢結果。
儘管可以很容易地查詢了,要用這個查詢的結果還要用到其它的函式。第一個是:
MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *result); |
該函式把結果轉換成“陣列”。你可能注意到了,該函式返回的是MYSQL_ROW變數型別。以下語句創立那樣的變數:
MYSQL_ROW row = mysql_fetch_row(res) |
如前所解釋的,變數row是一個字串陣列。也就是說,row[0]是陣列的第一個值,row[1]是陣列的第二個值...當我們用mysql_fetch_row的時候,接著變數row會取得結果的下一組的資料。當到了結果的尾部,該函式返回一負值。
使用資料集結束後,記得釋放資料集,否則會發生記憶體洩漏,釋放資料集函式如下:
|
釋放由mysql_store_result()
、mysql_use_result()
、mysql_list_dbs()等為一個結果集合分配的記憶體。當你用完了一個結果集合時,你必須呼叫mysql_free_result()
來釋放它使用的記憶體。
最後我們要關閉這個連線:
mysql_close(&mysql);
|
例子程式
執行一個select操作,從資料庫中取資料,並執行一個insert操作,往資料庫中插入資料,根據這兩個操作你可以自由的擴充套件為任意資料庫操作,
準備條件
1、已經安裝mysql,上有資料庫test,如果沒有執行
Create Databse test |
建立資料庫
2、test資料庫上有表t1,如果沒有,執行
CREATE TABLE `t1` ( `id` int(11) default NULL, `name` varchar(100) default NULL ) |
建立表t1
testsql.c:
// get the result from the executing select query query = "select * from t1"; t = mysql_real_query(&mysql,query,(unsigned int) strlen(query)); if (t) { printf("Error making query: %s/n", mysql_error(&mysql)); } else printf("[%s] made.../n", query); res = mysql_store_result(&mysql); while(row = mysql_fetch_row(res)) { for(t=0;t<mysql_num_fields(res);t++) { printf("%s ",row[t]); } printf("/n"); } printf("mysql_free_result.../n"); mysql_free_result(res); //free result after you get the result sleep(1); // execute the insert query query = "insert into t1(id, name) values(3, 'kunp')"; t = mysql_real_query(&mysql,query,(unsigned int) strlen(query)); if (t) { printf("Error making query: %s/n", mysql_error(&mysql)); } else printf("[%s] made.../n", query); mysql_close(&mysql); return 0; } |
編譯
假定mysql的標頭檔案在/usr/include/mysql,庫檔案在/usr/lib/mysql,執行下列命令進行編譯:
gcc testsql.c -I/usr/include/mysql -L/usr/lib/mysql -lmysqlclient |
相關文章
- [C++]C++程式設計例項C++程式設計
- C#多執行緒程式設計例項C#執行緒程式設計
- C# 2.0 套接字程式設計例項初探程式設計
- Jmeter beanshell程式設計例項JMeterBean程式設計
- 設計模式例項程式碼設計模式
- KafKa Java程式設計例項KafkaJava程式設計
- 微控制器C程式設計例項指導pdfC程式程式設計
- 遠端開發分散式C#程式設計例項分散式C#程式設計
- MySQL和MongoDB設計例項對比MySqlMongoDB
- Shell程式設計入門例項程式設計
- Qt 中Socket程式設計例項QT程式設計
- android socket程式設計例項Android程式設計
- XML程式設計例項(二) (轉)XML程式設計
- Java&CORBA程式設計例項JavaORB程式設計
- corba程式設計簡單例項ORB程式設計單例
- Java XML程式設計例項解析JavaXML程式設計
- c++ 連線mysql例項C++MySql
- MySQL與MongoDB設計例項對比QYMySqlMongoDB
- C++設計模式+例項視訊教程C++設計模式
- MySQL程式設計提示與樣例MySql程式設計
- shell程式設計例項--實現累加程式設計
- 【Akka】Akka入門程式設計例項程式設計
- Delphi趣味程式設計例項三則程式設計
- c# winform程式設計轉例C#ORM程式設計
- Oracle PL/SQL 程式設計基礎 例項OracleSQL程式設計
- MapReduce程式設計例項之倒排索引 1程式設計索引
- MapReduce程式設計例項之自定義排序程式設計排序
- 詳解 state 狀態模式及在 C++ 設計模式程式設計中的使用例項C++設計模式程式設計
- 多程式程式設計函式posix_spawn例項程式設計函式
- C語言MySQL程式設計示例C語言MySql程式設計
- Lotus Notes/Domino 的C API程式設計API程式設計
- shell script程式設計小結——附帶例項程式設計
- Spark程式設計環境搭建及WordCount例項Spark程式設計
- MapReduce程式設計例項之資料去重程式設計
- MapReduce程式設計例項之自定義分割槽程式設計
- shell程式設計例項1--參數列示程式設計
- 天氣例項ApiAPI
- C++學習隨筆——簡單的單例設計模式例項C++單例設計模式