日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

使用C語(yǔ)言操作MySQL數(shù)據(jù)庫(kù)

 看風(fēng)景D人 2014-03-19
1.連接數(shù)據(jù)庫(kù)。
  從C語(yǔ)言連接MySQL數(shù)據(jù)庫(kù)包含兩個(gè)步驟:
  a)初始化連接句柄結(jié)構(gòu);
  b)實(shí)際創(chuàng)建連接。
 
  首先使用mysql_init初始化連接句柄:
  MYSQL * mysql_init (MYSQL *);
  通常傳遞一個(gè)空指針給mysql_init這個(gè)函數(shù),它會(huì)返回一個(gè)指向新分配的連接句柄結(jié)構(gòu)的指針。如果傳遞一個(gè)已有的結(jié)構(gòu),他將被重新初始化。如果出錯(cuò),返回NULL。初始化成功后,則使用mysql_real_connect來(lái)創(chuàng)建一個(gè)實(shí)際的連接:
      MYSQL * mysql_real_connect(MYSQL * connection,
                      const char * server_host,
                      const char * sql_user_name,   
                      const char * sql_password,
                      const char *db_name,
                      unsigned int port_number,
                      const char * unix_socket_name,
                      unsigned int flags
        );
  connection必須是已經(jīng)初始化的連接句柄結(jié)構(gòu),server_host可以是主機(jī)名,也可以是IP地址,如果僅僅連接到本機(jī),可以使用 localhost來(lái)優(yōu)化連接類型。port_number和unix_socket_name應(yīng)該分別為0和NULL,除非改變了MYSQL安裝的默認(rèn) 設(shè)置。
 如果無(wú)法連接,返回NULL。完成連接后,在程序正常退出前,應(yīng)該使用mysql_close關(guān)閉這個(gè)連接句柄。
   void mysql_close(MYSQL * connection);
  現(xiàn)在我們?cè)噲D調(diào)用以上函數(shù)來(lái)建立一個(gè)對(duì)以上已經(jīng)建好的數(shù)據(jù)庫(kù)的訪問(wèn),程序?yàn)閏onnect1.c。內(nèi)容如下:
#include <stdlib.h>
#include <stdio.h>
#include "mysql.h"

int main (int argc, char *argv[])
{
      MYSQL *conn_ptr;
      conn_ptr=mysql_init(NULL); //連接初始化
      if(!conn_ptr){
              fprintf(stderr, "mysql_init failed\n");
              return EXIT_FAILURE;
      }

      conn_ptr = mysql_real_connect(conn_ptr, "localhost", "moldao","newpassword","moldao_test", 0, NULL, 0); //建立實(shí)際連接
      //參數(shù)分別為:初始化的連接句柄指針,主機(jī)名(或者IP),用戶名,密碼,數(shù)據(jù)庫(kù)名,0,NULL,0)后面三個(gè)參數(shù)在默認(rèn)安裝mysql>的情況下不用改
      if(conn_ptr){
              printf("Connection success\n");
              }
      else {
              printf("Connection failed\n");
      }

      mysql_close(conn_ptr); //關(guān)閉連接
      return EXIT_SUCCESS;
}
  然后編譯:
  #gcc -I/usr/include/mysql connect1.c -lmysqlclient -o connect1
 connect1.c:4:19: 錯(cuò)誤:mysql.h:沒(méi)有那個(gè)文件或目錄
  提示是沒(méi)有找到mysql.h,產(chǎn)生這個(gè)錯(cuò)誤的原因是沒(méi)有mysql.h文件,它在mysql-devel包中,需要安裝這個(gè)包:
     sudo yum install mysql-devel -y
  然后找一下:
     #locate mysql.h
     /usr/include/mysql/mysql.h
  這樣就可以找到這個(gè)頭文件了(-I的含義是在指定位置搜索頭文件,參見(jiàn)man gcc)。再次嘗試編譯:
  # gcc -I/usr/include/mysql connect1.c -lmysqlclient -o connect1
 /usr/bin/ld: cannot find -lmysqlclient
 collect2: ld 返回 1
  鏈接庫(kù)有問(wèn)題,找不到mysqlclient鏈接庫(kù),man gcc發(fā)現(xiàn)可以在后面用-L指定搜索位置,于是我們先找到mysqlclient庫(kù)的位置:
 locate *mysqlclient*
 /usr/lib/mysql/libmysqlclient.a
 /usr/lib/mysql/libmysqlclient.so
 /usr/lib/mysql/libmysqlclient.so.15
 /usr/lib/mysql/libmysqlclient.so.15.0.0
 /usr/lib/mysql/libmysqlclient_r.a
 /usr/lib/mysql/libmysqlclient_r.so
 /usr/lib/mysql/libmysqlclient_r.so.15
 /usr/lib/mysql/libmysqlclient_r.so.15.0.0
  這樣找到位置就可以編譯了:
    gcc -I/usr/include/mysql connect1.c -lmysqlclient -L/usr/lib/mysql -o connect1
  編譯成功,于是就可以運(yùn)行了,在此之前,確保mysqld已經(jīng)在運(yùn)行了:
  sudo /etc/rc.d/init.d/mysqld restart
  然后執(zhí)行生成的可執(zhí)行文件:
  ./connect1
 Connection success
  打印出了我們?cè)O(shè)計(jì)好了的連接成功的打印信息。這樣就通過(guò)C語(yǔ)言進(jìn)入了MySQL數(shù)據(jù)庫(kù)了。

  ##########################################
  #在以上這一段編譯這個(gè)connect1.c的文件過(guò)程了,出過(guò)兩次錯(cuò)誤,分別記錄如上,看起來(lái) #
  #解決的辦法很簡(jiǎn)單,但是自己當(dāng)時(shí)確實(shí)是很迷茫,不知什么原因,網(wǎng)上搜索的結(jié)果大都不得#
  #要領(lǐng),最終還是靠自己靜下心來(lái)看gcc的手冊(cè),man gcc才解決。                       #
  #P.S. man gcc真長(zhǎng)。 要冷靜!                                                     #
  ##########################################

2. 操作數(shù)據(jù)庫(kù)   
 進(jìn)入數(shù)據(jù)庫(kù)中之后,就可以開(kāi)始對(duì)數(shù)據(jù)庫(kù)進(jìn)行讀寫(xiě)操作了。
  數(shù)據(jù)庫(kù)的主要操作包括select, insert, update, delete四種。
  a)sql語(yǔ)句的嵌入:
      執(zhí)行SQL語(yǔ)句的主要API函數(shù)是:
      int mysql_query(MYSQL *connection, const char * query)
      接受已經(jīng)建立的連接結(jié)構(gòu)指針和文本字符串形式的有效SQL語(yǔ)句(句末不用分號(hào))。成功返回0。
      還有一個(gè)比較重要的函數(shù),mysql_affected_rows(),他返回?zé)o符號(hào)類型,當(dāng)使用printf時(shí),推薦使用%lu格式將其轉(zhuǎn)換為無(wú)符號(hào)長(zhǎng)整型。此函數(shù)返回受之前執(zhí)行的update,delete,insert等查詢影響的行數(shù)。
      my_ulonglong mysql_affected_rows(MYSQL *connection);
      MySQL返回被一個(gè)更新操作修改的行數(shù),但其他許多數(shù)據(jù)庫(kù)將僅僅因?yàn)橛涗浧ヅ鋡here字句而把它視為已經(jīng)更新過(guò)。
      通常對(duì)于mysql_函數(shù),返回值0表示沒(méi)有行受到影響,正數(shù)則是實(shí)際的結(jié)果,一般表示受語(yǔ)句影響的行數(shù)。
  
 b)select語(yǔ)句的使用:
  select語(yǔ)句是SQL語(yǔ)句中使用最頻繁的操作。    
  一個(gè)完整的提取數(shù)據(jù)過(guò)程應(yīng)該包含以下四個(gè)步驟:執(zhí)行查詢,提取數(shù)據(jù),處理數(shù)據(jù),清理。
  使用mysql_query來(lái)發(fā)送SQL語(yǔ)句,使用mysql_store_result或者mysql_use_result來(lái)提取數(shù)據(jù)。然后使用 mysql_fetch_row調(diào)用來(lái)處理數(shù)據(jù),最后,使用mysql_free_result來(lái)釋放查詢占用的內(nèi)存資源。
  mysql_use_result和mysql_store_result都是返回一個(gè)指向結(jié)果集結(jié)構(gòu)(result set structure)的指針,如果失敗則返回NULL。區(qū)別在于store將查詢到的數(shù)據(jù)庫(kù)中的結(jié)果直接放在這個(gè)結(jié)果集中,而use則不直接將最終數(shù)據(jù)庫(kù) 的數(shù)據(jù)結(jié)果放在這個(gè)結(jié)果集中。store其實(shí)就是把數(shù)據(jù)直接讀到本地內(nèi)存中,因此它比較適合數(shù)據(jù)量較小的查詢。use則類似于一種流的操作,并不是一次就 返回所有的結(jié)果。因此,對(duì)于這個(gè)結(jié)果集,必須反復(fù)調(diào)用mysql_fetch_row直到提取所有的數(shù)據(jù)。
  1)一次獲取所有的數(shù)據(jù):
  MYSQL_RES *mysql_store_result(MYSQL *connection);
  在成功調(diào)用mysql_query之后使用此函數(shù),將立即保存在客戶端中返回的所有數(shù)據(jù),并將指向此結(jié)果集的指針?lè)祷?。如果失敗則返回NULL。
  成功之后,可以用mysql_num_rows來(lái)得到返回記錄的數(shù)目,一般應(yīng)該是個(gè)正數(shù),若沒(méi)有返回行匹配,則返回0.
  my_ulonglong mysql_num_rows(MYSQL_RES *result);
  現(xiàn)在得到來(lái)數(shù)據(jù),可使用mysql_fetch_row來(lái)處理它,也可以使用mysql_data_seek,mysql_row_seek和mysql_row_tell在數(shù)據(jù)集中來(lái)回移動(dòng)。
  MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
  此函數(shù)從上面得到的結(jié)果集中提取一行,并把它放在一個(gè)行結(jié)構(gòu)中。當(dāng)數(shù)據(jù)用完或者出錯(cuò)時(shí)返回NULL。
  void mysql_data_seek(MYSQL_RES *result, my_ulonglong offset);
  此函數(shù)允許結(jié)構(gòu)集當(dāng)前指針的跳轉(zhuǎn),設(shè)置會(huì)被下一個(gè)mysql_fetch_row操作返回的行。offset是行號(hào),在0到總行數(shù)減1的范圍內(nèi)。傳遞0,則返回初始位置。
  MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES *result);
  此函數(shù)返回結(jié)果集的當(dāng)前位置。不能把它用于mysql_data_seek。
  完成來(lái)對(duì)數(shù)據(jù)的所有操作之后,必須調(diào)用mysql_free_result來(lái)讓MYSQL數(shù)據(jù)庫(kù)完成善后處理。
  void mysql_free_result(MYSQL_RES *result);


--------------------------------------使用范例--------------------------------------------------
 MYSQL my_connection;
 MYSQL_RES *res_ptr;
 MYSQL_ROW sqlrow;
 
  mysql_init(&my_connection);

  if(mysql_real_connect(&my_connection, "localhost", "moldao","password","moldao_test", 0, NULL, 0)){
              printf("Connection success\n");

              res = mysql_query(&my_connection, "select * from children where age < 10");

              if(res){
                      printf("select error: %s\n", mysql_error(&my_connection));

              }else {
                      res_ptr = mysql_store_result(&my_connection);
                      if(res_ptr){
                           printf("Retrieved %lu rows\n", (unsigned long)mysql_num_rows (res_ptr));
                         
                         while (sqlrow = mysql_fetch_row(res_ptr)){    
                                unsigned int field_count;
                                field_count =0;
                            while(field_count < mysql_field_count(&my_connection)){
                                printf("%s ", sqlrow[field_count]);field_count++;
                                         }
                              }
                              if(mysql_errno(&my_connection)){
                                      printf("Retrive error : %s\n", mysql_error(&my_connection));
                              }
                      }
              mysql_free_result(res_ptr);
              }
   mysql_close(&my_connection);
  -----------------------------------------------------------------------------------------------
  2)一次提取一行數(shù)據(jù)
  建議使用這種提取數(shù)據(jù)的方式。它能取得更好的網(wǎng)絡(luò)負(fù)載平衡,以及減少大數(shù)據(jù)集可能造成的存儲(chǔ)過(guò)載。但是它也增加來(lái)時(shí)延,并且在特殊的情況下,比如網(wǎng)絡(luò)鏈接在操作中途失敗時(shí),可能會(huì)得到不完整的數(shù)據(jù)甚至造成混亂。
 此時(shí)依靠mysql_use_result:
  MYSQL_RES *mysql_use_result(MYSQL * connection);
  與store一樣,出錯(cuò)返回NULL,成功則返回指向結(jié)果集對(duì)象的指針。
  --------------------------------------使用范例---------------------------------------------------------
 //這里只寫(xiě)取數(shù)據(jù)的部分
 res_ptr = mysql_store_result(&my_connection);
   if(res_ptr){
      while (sqlrow = mysql_fetch_row(res_ptr)){
          //display_row_or_dealwith_row_here;
          }
      }
 ------------------------------------------------------------------------------------------------
  
 c)update,insert,和delete語(yǔ)句的使用
  update, insert和delete這三個(gè)操作是不用返回任何數(shù)據(jù)的語(yǔ)句,他們都是使用mysql_query來(lái)執(zhí)行語(yǔ)句。        
  --------------------------------------使用范例------------------------------------------------
 int res = mysql_query(&my_connection, "SQL語(yǔ)句");
  if(!res){
      printf("operation success\naffected %lu rows\n", (unsigned long)mysql_affected_row (&my_connection));
     }
  else{
      fprintf(stderr, "failed error: %d: %s", mysql_errno(&my_connection), mysql_error(&my_connection));
     }
   -----------------------------------------------------------------------------------------------
  注意的是mysql_affected_row返回的是真正受到影響或者說(shuō)是被改變的行數(shù),而不僅僅是匹配where字句的行數(shù)。
 
 
3 一個(gè)完整的顯示數(shù)據(jù)庫(kù)中元數(shù)據(jù)和數(shù)據(jù)的例子:
#include <stdlib.h>
#include <stdio.h>

#include "mysql.h"

MYSQL my_connection;
MYSQL_RES *res_ptr;
MYSQL_ROW sqlrow;

void display_header();
void display_row();

int main (int argc, char *argv[])
{

      int first_row =1;
      int res;

      mysql_init(&my_connection); //連接初始化
/*      if(!conn_ptr){
              fprintf(stderr, "mysql_init failed\n");
              return EXIT_FAILURE;
      }
*/
      if(mysql_real_connect(&my_connection, "localhost", "moldao","savage","moldao_test", 0, NULL, 0)){
              printf("Connection success\n");

              res = mysql_query(&my_connection, "select * from children where age > 4");
              if(res){
                      fprintf(stderr, "Select error : %s\n", mysql_error(&my_connection));
                      }
              else{
                      res_ptr = mysql_use_result(&my_connection);
                      if(res_ptr){
                              display_header();
                              while((sqlrow = mysql_fetch_row(res_ptr))){
                                      if(first_row){
                                              display_header();
                                              first_row = 0;
                                              }
                                      display_row();
                                      }
                              if(mysql_errno(&my_connection)){
                                      fprintf(stderr, "Retrive error: %s\n", mysql_error(&my_connection));
                                      }
                              }
                      mysql_free_result(res_ptr);
                      }

              mysql_close(&my_connection);
      }
      else {
              fprintf(stderr,"Connection failed\n");

              if(mysql_errno(&my_connection)){
              fprintf(stderr, "Connection error %d: %s\n", mysql_errno(&my_connection), mysql_error (&my_connection));
                      }
     }

      return EXIT_SUCCESS;
}

void display_header(){
      MYSQL_FIELD *field_ptr;

      printf("Column details: \n");
      while((field_ptr = mysql_fetch_field(res_ptr))!= NULL){
              printf("\t Name: %s\n", field_ptr->name);
              printf("\t Type: ");
              if(IS_NUM(field_ptr->type)){
                      printf("Numeric field\n");
              }else{
                      switch(field_ptr->type){
                      case FIELD_TYPE_VAR_STRING:
                              printf("VARCHAR\n");break;
                     case FIELD_TYPE_LONG:
                              printf("LONG\n");break;
                      default:
                              printf("Type is %d, check in mysql_com.h\n", field_ptr->type);
                      }
              }

      printf("\t Max width %ld\n", field_ptr ->length);
      if(field_ptr->flags & AUTO_INCREMENT_FLAG)
              printf("\t Auto increment\n");
              printf("\n");
      }
}


void display_row(){
      unsigned int field_count;

      field_count = 0;
      while(field_count < mysql_field_count(&my_connection)){
      if(sqlrow[field_count])
              printf("%s ", sqlrow[field_count]);
      else printf("NULL");
      field_count++;

      }
      printf("\n");
}

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多