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"); } |
|
來(lái)自: 看風(fēng)景D人 > 《數(shù)據(jù)庫(kù)》