用C操作MySQL

來源:互聯網
上載者:User

簡介 
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的發行版本的不同,這個目錄也有所不同),因此你的程式頭部看起來有點這個樣子:  

#include <mysql.h>  

MySQL的變數類型和函數都包含在這個標頭檔當中 

然後,我們需要建立串連資料庫的變數,可以簡單地這麼做: 

MYSQL mysql; 
  

在串連資料庫之前,我們要調用以下函數初始化這個變數: 

mysql_init(&mysql); 
  

然後,調用mysql_real_connect函數: 

MYSQL *         STDCALL 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 clientflag);  

    該函數被調用串連到資料庫。host是MySQL伺服器的主機名稱,user是登入的使用者名稱,passwd是登入密碼,db是要串連的資料庫,port是MySQL伺服器的TCP/IP連接埠,unix_socket是連線類型,clientflag是MySQL運行成ODBC資料庫的標記。在這篇文章當中該標記設成0,串連尋建立後,這個函數返回0。 

現在可以串連資料庫,進行查詢了: 

char *query; 
  

  

使用這個字串我們可以創立任何SQL查詢語句進行查詢。執行這個查詢的函數是: 

int STDCALL mysql_real_query(MYSQL *mysql, const char *q, unsigned int length); 
  

  

mysql是我們前面用過的變數,q是SQL查詢語句,length是這個查詢語句的長度。如果查詢成功,函數返回0。  

查詢之後,我們要到一個MYSQL_RES變數來使用查詢的結果。以下這行創立這個變數: 

MYSQL_RES *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會取得結果的下一組的資料。當到了結果的尾部,該函數返回一負值。 

使用資料集結束後,記得釋放資料集,否則會發生記憶體流失,釋放資料集函數如下: 

void mysql_free_result(MYSQL_RES *result) 
  

  

釋放由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: 
  
/* testsql.c 
  ** An example to use MYSQL C API 
  ** Copyright 2004 Coon Xu. 
  ** Author: Coon Xu 
  ** Date: 05 Nov 2004 
  */ 
    
  #include <mysql.h> 
  #include <stdio.h> 
int main(){ 
   MYSQL mysql;     // need a instance to init 
   MYSQL_RES *res; 
   MYSQL_ROW row; 
   char *query; 
   int t,r; 
 // connect the database  
   mysql_init(&mysql); 
   if (!mysql_real_connect(&mysql,"localhost", "mmim", "mmim", "test",0,NULL,0)) 
   { 
       printf( "Error connecting to database: %s/n",mysql_error(&mysql)); 
   } 
   else printf("Connected.../n"); 

 // 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 

  

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.