Linux下C語言執行MySQL語句
阿新 • • 發佈:2019-01-05
執行SQL語句的增、刪、改、查的主要API函式為:
int mysql_query(MYSQL *connection, const char *query);
函式接收引數連線控制代碼和字串形式的有效SQL語句(沒有結束的分號,這與mysql工具不同)。如果成功,它返回0。
如果包含二進位制資料的查詢,要使用mysql_real_query.
檢查受查詢影響的行數:
my_ulonglong mysql_affected_rows(MYSQL *connection);
my_ulonglong是無符號長整形,為%lu格式這個函式返回受之前執行update,insert或delete查詢影響的行數。
例子
資料庫中有一個student表
CREATE TABLE student (
student_no varchar(12) NOT NULL PRIMARY KEY,
student_name varchar(12) NOT NULL
);
增、刪、改程式碼:
#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
// 相關函式:
// 這是在成功呼叫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);
示例程式碼:
#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更好。
處理返回的資料
// 相關函式和定義:
// 返回結果集中的欄位(列)數目
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
程式碼示例:
#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);
}