Linux程式設計——C語言連線MySQL資料庫
MySQL是Linux系統下廣泛使用的開源免費資料庫,是Linux應用程式資料儲存的首選。許多釋出的Linux版本是自帶MySQL的,但是也有些釋出版本是不帶的(比如我現在用的Ubuntu),那就需要手動安裝。在Synaptic Packet Management中搜索“mysql”,可以找到“mysql-client"包,點選安裝即可。
安裝好的MySQL是在命令列下執行的,這對於許多經常在Windows下開發程式,習慣使用圖形化工具的人來說是很痛苦的。因此我們需要 安裝MySQL圖形化管理工具MySQL Administrator和MySQL Query Brower。開啟Ubuntu Software Center,輸入”mysql"搜尋,可以看到這兩個工具,點選安裝即可。
安裝了以上的軟體包後,我們可以正常使用MySQL完成資料管理工作,但是很多時候我們需要通過編寫程式訪問MySQL。此時,在程式中需要載入MySQL驅動標頭檔案,但是預設這些驅動包是沒有安裝的,因此我們需要在Synaptic Packet Management中找到"libmysqld-dev"包並安裝。
用C語言連線MySQL資料庫有兩個步驟:
1)初始化一個連線控制代碼結構
2)建立連線
所用到的函式如下:
使用上面函式實現MySQL資料庫連線的程式如下:#include <mysql.h> MYSQL *mysql_init(MYSQL *); // 初始化連線控制代碼 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); //建立連線 void mysql_close(MYSQL *connection); //關閉連線 int mysql_options(MYSQL *connection, enum option_to_set, const char *argument); //設定連線選項 option_to_set的值為下列三個值之一: MySQL_OPT_CONNECT_TIMEOUT //連線超時前的等待秒數 MySQL_OPT_COMPRESS //網路連線中使用壓縮機制 MySQL_INIT_COMMAND //每次建立連線後傳送的命令
程式編譯執行後顯示“Connection success"表明程式已經成功與MySQL資料庫建立連線,並在程式結束前關閉連線。/* * gcc -I/usr/include/mysql connect1.c -L/usr/lib/mysql -lmysqlclient -o connect1 */ #include <stdlib.h> #include <stdio.h> #include <mysql.h> int main() { MYSQL *conn_ptr; // 定義連線控制代碼 conn_ptr = mysql_init(NULL); // 初始化連線控制代碼 if(!conn_ptr) { fprintf(stderr, "mysql_init falied\n"); return EXIT_FAILURE; } // 建立連線 conn_ptr = mysql_real_connect(conn_ptr, "localhost", "root", "pwd", "test", 0, NULL, 0); if(conn_ptr) { printf("Connection success\n"); } else { printf("Connection failed\n"); } // 關閉連線 mysql_close(conn_ptr); return EXIT_SUCCESS; }
上面的程式是在假設沒有錯誤的情況下執行,如果資料庫連線過程中出現了錯誤,我們就需要以下兩個函式來處理錯誤資訊:
unsigned int mysql_errno(MYSQL *connection); //返回錯誤程式碼(非零值)
char *mysql_error(MYSQL *connection); //返回錯誤資訊
具體使用方法如下:/*
* gcc -I/usr/include/mysql connect2.c -L/usr/lib/mysql -lmysqlclient -o connect2
*/
#include <stdlib.h>
#include <stdio.h>
#include <mysql.h>
int main(int argc, char *argv[])
{
MYSQL connection;
mysql_init(&connection); //初始化連線
if(mysql_real_connect(&connection, "localhost", "root", "unknown", "test", 0, NULL, 0)) //建立連線
{
printf("Connection success\n");
mysql_close(&connection);
}
else //連線失敗列印錯誤資訊
{
fprintf(stderr, "Connection failed\n");
if(mysql_errno(&connection))
{
fprintf(stderr, "Connection error %d: %s\n", mysql_errno(&connection), mysql_error(&connection));
}
}
return EXIT_SUCCESS;
}
執行上述程式,如果MySQL的登陸密碼不是unknown則列印錯誤資訊(拒絕訪問——Access denied)。程式訪問資料庫不只是與資料庫建立連線,更重要的是通過SQL語句的執行查詢或改變資料庫中資料。執行SQL語句可以通過下列函式實現。
//執行SQL語句,成功返回0
int mysql_query(MYSQL *connection, const char *query);
SQL語句分為兩類,返回資料的SQL(SELECT)和不返回資料的SQL(UPDATE、DELETE、INSERT)。
1)不返回資料的SQL// 返回查詢受影響的行
my_ulong mysql_affected_rows(MYSQL *connection);
對一段SQL語句執行後可以通過呼叫此函式檢視SQL語句執行後,資料庫中資料狀態改變的行數,以此判斷SQL的執行成功與否。
/*
* gcc -I/usr/include/mysql insert1.c -L/usr/lib/mysql -lmysqlclient -o insert1
*/
#include <stdlib.h>
#include <stdio.h>
#include <mysql.h>
int main(int argc, char *argv[])
{
int res;
MYSQL connection;
mysql_init(&connection);
if(mysql_real_connect(&connection, "localhost", "root", "pwd", "test", 0, NULL, 0))
{
printf("Connection success\n");
res = mysql_query(&connection, "INSERT INTO children(fname, age) VALUES('ann', 3)");
if(!res)
{
printf("Inserted %lu rows\n", (unsigned long)mysql_affected_rows(&connection)); //列印受影響的行數
}
else
{
fprintf(stderr, "Insert error %d: %s\n", mysql_errno(&connection), mysql_error(&connection));
}
mysql_close(&connection);
}
else
{
fprintf(stderr, "Connection failed\n");
if(mysql_errno(&connection))
{
fprintf(stderr, "Connection error %d: %s\n", mysql_errno(&connection), mysql_error(&connection));
}
}
return EXIT_SUCCESS;
}
2)返回資料的SQL
返回資料的SQL是指通過查詢語句從資料庫中取出滿足條件的資料記錄。//一次提取所有資料
MYSQL_RES *mysql_store_result(MYSQL *connection);
//一次提取一行資料
MYSQL_RES *mysql_use_result(MYSQL *connection);
//清除結果集物件
void mysql_free_result(MYSQL_RES *result);
使用方法如下所示:#include <stdlib.h>
#include <stdio.h>
#include <mysql.h>
MYSQL connection;
MYSQL_RES *sqlres;
MYSQL_ROW sqlrow;
int main(int argc, char *argv[])
{
int res;
mysql_init(&connection);
if(mysql_real_connect(&connection, "localhost", "root", "pwd", "mysql", 0, NULL, 0))
{
printf("Connection success\n");
res = mysql_query(&connection, "SELECT user, password, host from user");
if(res)
{
printf("SELECT error: %s\n", mysql_error(&connection));
}
else
{
// 一次取全部資料
sqlres = mysql_store_result(&connection);
if(sqlres)
{
printf("Retrieved %lu rows\n", (unsigned long)mysql_num_rows(sqlres));
while((sqlrow = mysql_fetch_row(sqlres)))
{
printf("Fetched data...\n");
}
if(mysql_errno(&connection))
{
fprintf(stderr, "Retrive error: %s\n", mysql_error(&connection));
}
mysql_free_result(sqlres);
}
// 一次取一行資料
/*sqlres = mysql_use_result(&connection);
if(sqlres)
{
while((sqlrow = mysql_fetch_row(sqlres)))
{
printf("Fetched data...\n");
}
if(mysql_errno(&connection))
{
printf("Retrive error: %s\n", mysql_error(&connection));
}
mysql_free_result(sqlres);
}*/
}
mysql_close(&connection);
}
else
{
fprintf(stderr, "Connection failed\n");
if(mysql_errno(&connection))
{
fprintf(stderr, "Connection error %d: %s\n", mysql_errno(&connection), mysql_error(&connection));
}
}
return EXIT_SUCCESS;
}
一次取全部資料增加了網路負載,但是可以保證資料的完整性。一次取一行資料平衡了網路負載,減小了資料開銷,但是增加了時延,因為每次取資料都必須通過網路。
最後一個比較重要的功能是對資料集中的資料進行處理,可能通過列號或者列名來讀取資料。
//返回結果集中的欄位數目
unsigned int mysql_field_count(MYSQL *connection);
MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result);
void display_row()
{
unsigned int field_count;
field_count = 0;
while(field_count < mysql_field_count(&connection))
{
printf("%s ", sqlrow[field_count]);
field_count++;
}
printf("\n");
}
小結:通過以上分析,可以瞭解在Linux作業系統環境下如何通過程式建立與MySQL資料的連線,並且通過庫函式的呼叫可以實現對資料庫的增刪改查操作,在出現錯誤時,通過函式呼叫可以返回錯誤程式碼,也可以直接返回錯誤資訊。