c 窗体程序 mysql_C\C++开发MySQL程序简介(下)
如果需要向數(shù)據(jù)庫中存儲BLOB數(shù)據(jù),則不能單純的使用字符串,因?yàn)锽LOB數(shù)據(jù)中很可能含有0。
一般有兩種方法用來存儲BLOB數(shù)據(jù),一個(gè)是通過MYSQL提供的轉(zhuǎn)義函數(shù):
unsigned long mysql_real_escape_string(MYSQL *mysql, char *to, const char *from, unsigned long length)
該函數(shù)將“from”中的字符串編碼為轉(zhuǎn)義SQL字符串。將結(jié)果置于“to”中,并添加1個(gè)終結(jié)用NULL字節(jié)。編碼的
字符為NUL (ASCII 0)、‘\n’、‘\r’、‘\’、‘'’、‘"’等。
注意,必須為“to”緩沖區(qū)分配至少length*2+1字節(jié),以保證在最壞情況下不會溢出。
另一種方法則是通過MYSQL預(yù)處理函數(shù)進(jìn)行BLOB數(shù)據(jù)的存儲。
下面先介紹預(yù)處理函數(shù)。
MySQL客戶端/服務(wù)器協(xié)議提供了預(yù)處理語句。該功能采用了由mysql_stmt_init()初始化函數(shù)返回的MYSQL_STMT語句處理程序數(shù)據(jù)結(jié)構(gòu)。對于多次執(zhí)行的語句,預(yù)處理執(zhí)行是一種有效的方式。首先對語句進(jìn)行解析,為執(zhí)行作好準(zhǔn)備。接下來,在以后使用初始化函數(shù)返回的語句句柄執(zhí)行一次或多次。
對于多次執(zhí)行的語句,預(yù)處理執(zhí)行比直接執(zhí)行快,主要原因在于,僅對查詢執(zhí)行一次解析操作。在直接執(zhí)行的情況下,每次執(zhí)行語句時(shí),均將進(jìn)行查詢。此外,由于每次執(zhí)行預(yù)處理語句時(shí)僅需發(fā)送參數(shù)的數(shù)據(jù),從而減少了網(wǎng)絡(luò)通信量。
預(yù)處理語句的另一個(gè)優(yōu)點(diǎn)是,它采用了二進(jìn)制協(xié)議,從而使得客戶端和服務(wù)器之間的數(shù)據(jù)傳輸更有效率。
下述語句可用作預(yù)處理語句:CREATE TABLE、DELETE、DO、INSERT、REPLACE、SELECT、SET、UPDATE、以及大多數(shù)SHOW語句。在MySQL 5.1中,不支持其他語句。
預(yù)處理函數(shù)有兩個(gè)核心的數(shù)據(jù)類型,MYSQL_STMT和MYSQL_BIND,關(guān)于MYSQL_STMT完全不需要理解,關(guān)于MYSQL_BIND需要查看下手冊,接下來的一些函數(shù)需要用到它。
/*初始化,使用預(yù)處理語句必須先調(diào)用該函數(shù)*/
MYSQL_STMT *mysql_stmt_init(MYSQL *mysql);
/*準(zhǔn)備語句*/
int mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned long length);
/*綁定參數(shù)*/
my_bool mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind);
/*綁定結(jié)果*/
my_bool mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind);
/*執(zhí)行SQL語句*/
int mysql_stmt_execute(MYSQL_STMT *stmt);
/*使用完后需要釋放資源*/
my_bool mysql_stmt_close(MYSQL_STMT *);
對于預(yù)處理流程,MYSQL提供了很多和普通流程同樣的接口,比如獲取記錄集,獲取一行記錄,獲取SQL語句影響的行數(shù),以及錯(cuò)誤處理函數(shù)等,只是在函數(shù)名中加入了stmt,查下手冊就可以了。
這里稍微解釋下mysql_stmt_prepare函數(shù)和mysql_stmt_bind_param函數(shù),一般來說,需要使用到預(yù)處理流程的,都是SQL語句格式固定,只是有一兩個(gè)值在變化,比如:
INSERT INTO mytbl VALUES(?,?,?)
這里的三個(gè)問號就是三個(gè)參數(shù),如果你寫過存儲過程應(yīng)該很好理解。
通過將問號字符“?”嵌入到SQL字符串的恰當(dāng)位置,應(yīng)用程序可包含SQL語句中的一個(gè)或多個(gè)參數(shù)標(biāo)記符。
標(biāo)記符僅在SQL語句中的特定位置時(shí)才是合法的。例如,它可以在INSERT語句的VALUES()列表中(為行指定列值),或
與WHERE子句中某列的比較部分(用以指定比較值)。但是,對于ID(例如表名或列名),不允許使用它們,不允許指定二進(jìn)
制操作符(如等于號“=”)的操作數(shù)。后一個(gè)限制是有必要的,原因在于,無法確定參數(shù)類型。一般而言,參數(shù)僅在DML(數(shù)據(jù)
操作語言)語句中才是合法的,在DDL(數(shù)據(jù)定義語言)語句中不合法。
將這條語句prepare好后,就可以進(jìn)行綁定參數(shù)了,當(dāng)然在調(diào)用函數(shù)前,需要先將MYSQL_BIND結(jié)構(gòu)體準(zhǔn)備好,比如上邊這條語句有3個(gè)參數(shù),那么就需要準(zhǔn)備一個(gè)數(shù)組
MYSQL_BIND bind[3]={0};
......
mysql_stmt_bind_param(stmt,bind);
再回到開頭的問題,如果需要存儲BLOB數(shù)據(jù),那么我們可以設(shè)置MYSQL_BIND結(jié)構(gòu)體綁定到一個(gè)buffer,然后執(zhí)行SQL語句即可
MYSQL * mysql = NULL;
......
MSYQL_STMT * stmt = mysql_stmt_init(mysql);
const char * strSql = "insert into mytable(id,content) values(1,?)";
mysql_stmt_prepare(stmt,strSql,strlen(strSql));
char buffer[128]={0};
int len = 128;//數(shù)據(jù)的長度
/*通過memcpy等向buffer中復(fù)制數(shù)據(jù)*/
MYSQL_BIND bind;
bind.buffer_type = MYSQL_TYPE_BLOB;
bind.buffer = buffer;
bind.buffer_length = &len; //這個(gè)長度是指緩沖區(qū)的最大長度
bind.is_null = 0;
bind.length = &len;//這個(gè)指數(shù)據(jù)的實(shí)際長度
mysql_stmt_bind_param(stmt,&bind);
mysql_stmt_execute(stmt);
...
mysql_stmt_close(stmt);
不管使用普通流程還是預(yù)處理流程,在讀取BLOB數(shù)據(jù)時(shí),你需要用到下邊的函數(shù)來獲取數(shù)據(jù)的長度:
/*該函數(shù)返回一個(gè)指針,你可以通過索引值來獲得相應(yīng)的列的值的長度*/
/*每次獲取一行新記錄,你都需要調(diào)用該函數(shù)*/
unsigned long *mysql_fetch_lengths(MYSQL_RES *result); 下一篇將會給出一些比較完整的例子
總結(jié)
以上是生活随笔為你收集整理的c 窗体程序 mysql_C\C++开发MySQL程序简介(下)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 车开着开着就熄火了,电瓶灯一闪一闪的是怎
- 下一篇: 全国2021年年末保有的汽车中的燃油汽车