本文出自 http://blog.csdn.net/shuangde800
執行SQL語句的增、删、改、查的主要API函數為:
[cpp] view plain copy
- int mysql_query(MYSQL *connection, const char *query);
函數接收參數連接配接句柄和字元串形式的有效SQL語句(沒有結束的分号,這與mysql工具不同)。如果成功,它傳回0。
如果包含二進制資料的查詢,要使用mysql_real_query.
檢查受查詢影響的行數:
[cpp] view plain copy
- my_ulonglong mysql_affected_rows(MYSQL *connection);
my_ulonglong是無符号長整形,為%lu格式
這個函數傳回受之前執行update,insert或delete查詢影響的行數。
例子
資料庫中有一個student表
[sql] view plain copy
- CREATE TABLE student (
- student_no varchar(12) NOT NULL PRIMARY KEY,
- student_name varchar(12) NOT NULL
- );
增、删、改代碼:
[cpp] view plain copy
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "mysql.h"
- #include "errmsg.h"
- #include "mysqld_error.h"
- MYSQL conn;
- void connection(const char* host, const char* user, const char* password, const char* database) {
- mysql_init(&conn); // 注意取位址符&
- if (mysql_real_connect(&conn, host, user, password, database, 0, NULL, 0)) {
- printf("Connection success!\n");
- } else {
- fprintf(stderr, "Connection failed!\n");
- if (mysql_errno(&conn)) {
- fprintf(stderr, "Connection error %d: %s\n", mysql_errno(&conn), mysql_error(&conn));
- }
- exit(EXIT_FAILURE);
- }
- }
- void insert() {
- int res = mysql_query(&conn, "INSERT INTO student(student_no,student_name) VALUES('123465', 'Ann')");
- if (!res) {
- printf("Inserted %lu rows\n", (unsigned long)mysql_affected_rows(&conn));
- } else {
- fprintf(stderr, "Insert error %d: %s\n", mysql_errno(&conn), mysql_error(&conn));
- }
- }
- void update() {
- int res = mysql_query(&conn, "UPDATE student SET student_name='Anna' WHERE student_no='123465'");
- if (!res) {
- printf("Update %lu rows\n", (unsigned long)mysql_affected_rows(&conn));
- } else {
- fprintf(stderr, "Update error %d: %s\n", mysql_errno(&conn), mysql_error(&conn));
- }
- }
- void delete() {
- int res = mysql_query(&conn, "DELETE from student WHERE student_no='123465'");
- if (!res) {
- printf("Delete %lu rows\n", (unsigned long)mysql_affected_rows(&conn));
- } else {
- fprintf(stderr, "Delete error %d: %s\n", mysql_errno(&conn), mysql_error(&conn));
- }
- }
- int main (int argc, char *argv[]) {
- connection("localhost", "root", "shuang", "shuangde");
- delete();
- mysql_close(&conn);
- exit(EXIT_SUCCESS);
- }
傳回資料的語句:select
SQL最常見的用法是提取資料而不是插入或更新資料。資料是用select語句提取的
C應用程式提取資料一般需要4個步驟:
1、執行查詢
2、提取資料
3、處理資料
4、必要的清理工作
就像之前的insert和update一樣,使用mysql_query來發送SQL語句,然後使用mysql_store_result或mysql_use_result來提取資料,具體使用哪個語句取決于你想如何提取資料。接着,将使用一系列mysql_fetch_row來處理資料。最後,使用mysql_free_result釋放查詢占用的記憶體資源。
一次提取所有資料:mysql_store_result
[cpp] view plain copy
- // 相關函數:
- // 這是在成功調用mysql_query之後使用此函數,這個函數将立刻儲存在用戶端中傳回的所有資料。它傳回一個指向結果集結構的指針,如果失敗傳回NULL
- MYSQL_RES *mysql_store_result(MYSQL *connection);
- // 這個函數接受由mysql_store_result傳回的結果結構集,并傳回結構集中的行數
- my_ulonglong mysql_num_rows(MYSQL_RES *result);
- // 這個函數從使用mysql_store_result得到的結果結構中提取一行,并把它放到一個行結構中。當資料用完或發生錯誤時傳回NULL.
- MYSQL_ROW mysql_fetch_row(MYSQL_RES *resutl);
- // 這個函數用來在結果集中跳轉,設定将會被下一個mysql_fetch_row操作傳回的行。參數offset是一個行号,它必須是在0~結果總行數-1的範圍内。傳遞
- // 0将會導緻下一個mysql_fetch_row調用傳回結果集中的第一行。
- void mysql_data_seek(MYSQL_RES *result, my_ulonglong offset);
- // 傳回一個偏移值,它用來表示結果集中的目前位置。它不是行号,不能把它用于mysql_data_seek
- MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES *result);
- // 這将在結果集中移動目前的位置,并傳回之前的位置
- MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET offset);
- // 完成所有對資料的操作後,必須總是調用這個來善後處理
- void mysql_free_result(MYSQL_RES *result);
示例代碼:
[cpp] view plain copy
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "mysql.h"
- #include "errmsg.h"
- #include "mysqld_error.h"
- MYSQL conn;
- MYSQL_RES *res_ptr;
- MYSQL_ROW sqlrow;
- void connection(const char* host, const char* user, const char* password, const char* database) {
- mysql_init(&conn); // 注意取位址符&
- if (mysql_real_connect(&conn, host, user, password, database, 0, NULL, 0)) {
- printf("Connection success!\n");
- } else {
- fprintf(stderr, "Connection failed!\n");
- if (mysql_errno(&conn)) {
- fprintf(stderr, "Connection error %d: %s\n", mysql_errno(&conn), mysql_error(&conn));
- }
- exit(EXIT_FAILURE);
- }
- }
- int main (int argc, char *argv[]) {
- connection("localhost", "root", "shuang", "shuangde");
- int res = mysql_query(&conn, "SELECT * from student");
- if (res) {
- fprintf(stderr, "SELECT error: %s\n", mysql_error(&conn));
- } else {
- res_ptr = mysql_store_result(&conn);
- if (res_ptr) {
- printf("Retrieved %lu rows\n", (unsigned long)mysql_num_rows(res_ptr));
- while ((sqlrow = mysql_fetch_row(res_ptr))) {
- printf("Fetched data...\n") ;
- }
- if (mysql_errno(&conn)) {
- fprintf(stderr, "Retrive error: %s\n", mysql_error(&conn));
- }
- mysql_free_result(res_ptr);
- }
- }
- mysql_close(&conn);
- exit(EXIT_SUCCESS);
- }
一次提取一行資料:mysql_use_result
使用方法和mysql_store_result完全一樣,把上面代碼的mysql_store_result改為mysql_use_result即可。
mysql_use_result具備資源管理方面的實質性好處,更好地平衡了網絡負載,以及減少了可能非常大的資料帶來的存儲開銷,但是不能與mysql_data_seek、mysql_row_seek、mysql_row_tell、mysql_num_rows一起使用。如果資料比較少,用mysql_store_result更好。
處理傳回的資料
[cpp] view plain copy
- // 相關函數和定義:
- // 傳回結果集中的字段(列)數目
- unsigned int mysql_field_count(MYSQL *connection);
- // 将中繼資料和資料提取到一個新的結構中
- MYSQL_FIELD *mysql_fetch_field(MYSQL *result);
- // 這個函數用來覆寫目前的字段編号,該編号會随着每次mysql_fetch_field調用而自動增加。如果給offset傳遞0,那麼将跳回第1列
- MYSQL_FIELD_OFFSET mysql_field_seek(MYSQL *result, MYSQL_FIELD_OFFSET offset);
- // MYSQL_FIELD定義在sql.h中,是指向字段結構資料的指針,有關于列的資訊。有成員:
- char *name; // 列名,為字元串
- char *table; // 列所屬表名
- char *def; // 如果調用mysql_list_fields,它将包含該列的預設值
- enum enum_field_types type; // 列類型
- unsigned int length; // 列寬
- unsigned int max_length; // 如果使用mysql_store_result,它将包含以位元組為機關的提取的最長列值的長度,如果使用mysql_use_result,将不會被設定
- unsigned int flags; // 關于列定義的标志,與得到的資料無關.常見的标志的含義有:
- // NOT_NULL_FLAG
- // PRI_KEY_FLAG
- // UNSIGNED_FLAG
- // AUTO_INCREMENT_FLAG
- // BINARY_FLAG等
- unsigned int decimals; // 小數點後的數字個數。
- // 列類型相當廣泛,完整的清單見頭檔案mysql_com.h,常見的有:
- // FIELD_TYPE_DECIMAL
- // FIELD_TYPE_LONG
- // FIELD_TYPE_STRING
- // FIELD_TYPE_VAR_STRING
- //一個特别有用的預定義宏: IS_NUM,當字段類型為數字時,傳回true
代碼示例:
[cpp] view plain copy
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "mysql.h"
- #include "errmsg.h"
- #include "mysqld_error.h"
- MYSQL conn;
- MYSQL_RES *res_ptr;
- MYSQL_ROW sqlrow;
- void connection(const char* host, const char* user, const char* password, const char* database) {
- mysql_init(&conn); // 注意取位址符&
- if (mysql_real_connect(&conn, host, user, password, database, 0, NULL, 0)) {
- printf("Connection success!\n");
- } else {
- fprintf(stderr, "Connection failed!\n");
- if (mysql_errno(&conn)) {
- fprintf(stderr, "Connection error %d: %s\n", mysql_errno(&conn), mysql_error(&conn));
- }
- exit(EXIT_FAILURE);
- }
- }
- void display_row() {
- unsigned int field_count = mysql_field_count(&conn);
- int i = 0;
- while (i < field_count) {
- if (sqlrow[i]) printf("%s ", sqlrow[i]);
- else printf("NULL");
- i++;
- }
- printf("\n");
- }
- 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 Table: %s\n", field_ptr->table);
- 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");
- break;
- default:
- printf("Type is %d, check in msyql_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 increments\n");
- printf("\n");
- }
- }
- int main (int argc, char *argv[]) {
- connection("localhost", "root", "shuang", "shuangde");
- int res = mysql_query(&conn, "SELECT * from student");
- if (res) {
- fprintf(stderr, "SELECT error: %s\n", mysql_error(&conn));
- } else {
- res_ptr = mysql_use_result(&conn);
- if (res_ptr) {
- int first = 1;
- while ((sqlrow = mysql_fetch_row(res_ptr))) {
- if (first) {
- display_header();
- first = 0;
- }
- display_row();
- }
- if (mysql_errno(&conn)) {
- fprintf(stderr, "Retrive error: %s\n", mysql_error(&conn));
- }
- mysql_free_result(res_ptr);
- }
- }
- mysql_close(&conn);
- exit(EXIT_SUCCESS);
- }