1、
Mysql預先處理簡介
預先處理的意思是先提交sql語句到mysql服務端,執行先行編譯,用戶端執行sql語句時,只需上傳輸入參數即可,這點和預存程序有點相似。
一般而言,預先處理的執行效率相對於一般的sql執行操作,效率比較高。由於用戶端上傳的或是讀取的結果集是綁定輸入記憶體位址和輸出記憶體位址,對於一些二進位流,或大資料量的儲存和讀取顯得尤為方便。
2、
參考說明
具體的可以參考mysql的操作手冊,裡面第25章,C API庫,裡面有詳細的說明。連結地址如下:http://dev.mysql.com/doc/refman/5.1/zh/apis.html#c-api-prepared-statements
3、以一個簡單的sql查詢語句來簡要說明一下mysql預先處理的功能。
調用mysql c api的預先處理函數,執行預先處理功能的步驟一般如下:
1)
先調用mysql_init(),初始化一個MYSQL對象,用於與資料庫的連結控制代碼
2)
調用mysql_real_connect()連結資料庫服務端
3)
調用mysql_stmt_init()初始化一個MYSQL_STMT對象,用於處理對應的預先處理操作
4)
調用mysql_stmt_prepare()介面,上傳預先處理的sql語句
5)
定義相應的MYSQL_BIND資料結構,調用mysql_stmt_bind_param用於綁定輸入參數
6)
如果有輸出結果集,可以選擇調用mysql_stmt_result_metadata()介面以結果集MYSQL_RES形式返回預先處理語句中繼資料。
7)
調用mysql_stmt_execute()執行相應的sql查詢操作
8)
如果有輸出結果,調用mysql_stmt_bind_result將輸出結果綁定到MYSQL_BIND資料結構對象上,同時調用mysql_stmt_store_result()將所有的結果集儲存到用戶端的緩衝區中,並通過mysql_stmt_fetch()來進行調用擷取返回的每行的值
//初始化資料和連結控制代碼MYSQL* pSql = new MYSQL;Mysql_init(pSql);MYSQL_STMT* pSql_Stmt = mysql_stmt_int(pSql);//連結資料庫Mysql_read_connect(pSql, “127.0.0.1”, “root”, “123456”, “STMT”, NULL, 0);//預先處理的sql語句,後面的’?’表示輸入參數CString strSql = “Select Name, PhotoData from PhotoData where ID = ? “; //準備字串查詢指向的sql語句 mysql_stmt_prepare(pSql_Stmt, strSql.Getbuffer(0), strSql.getlength()); //聲明輸入參數的綁定資料結構 MYSQL_BIND v_pParaBind[1]; //只有一個輸入參數,綁定一個即可 My_Bool v_pParaIsNull[1]; //用於標明是輸入還是輸出 Unsigned long ParaLength[1]; //用於儲存輸入參數長度或輸出結果長度 memset(v_pParaBind, 0, sizeof(v_pParaBind));memset(v_pParaIsNull, 0, sizeof(v_pParaIsNull));memset(Paralength, 0, sizeof(Paralength)); int nID = 18; //假定前面的那個select語句的輸入參數為18v_pParaBind [0].buffer = (char*)& nID;v_pParaBind [0].buffer_length = sizeof(int);Paralength[0] = sizeof(int);v_pParaBind [0].length = &(Paralength[0]);v_pParaBind [0].is_null = &( v_pParaIsNull [0]);v_pParaBind [0].buffer_type = MYSQL_TYPE_LONG; //標明輸入的類型是INT型 //綁定輸入參數值 Mysql_stmt_bind_param(pSql_Stmt, v_pParaBind); //執行sql查詢操作 Mysql_stmt_execute(pSql_Stmt); //綁定輸出結果的MYSQL_BIND結構 MYSQL_BIND v_pResultBind[2]; //輸出結果有兩個資料列,定義兩個BIND分別對應 My_bool v_pResultIsNull[2]; Unsigned long ResultLength[2]; char szName[200] = {0};char szPhotoData[2000] = {0}; memset(v_pResultBind, 0, sizeof(v_pResultBind));memset(v_pResultIsNull, 0, sizeof(v_pResultIsNull));memset(ResultLength, 0, sizeof(ResultLength)); v_pResultBind[0].buffer = szName; //用於儲存返回的結果資料v_pResultBind[0].length = &(ResultLength[0]); //用於儲存返回結果長度v_pResultBind[0].is_null = &(v_pResultIsNull[0]);v_pResultBind[0].buffer_type = MYSQL_TYPE_STRING; v_pResultBind[1].buffer = szPhotoData; v_pResultBind[1].length = &(ResultLength[1]); v_pResultBind[1].is_null = &(v_pResultIsNull[1]);v_pResultBind[1].buffer_type = MYSQL_TYPE_BLOB; mysql_stmt_bind_result(pSql_Stmt, v_pResultBind); //擷取每行的值 Mysql_stmt_store_result(pSql_Stmt); While(!mysql_stmt_fetch(pSql_Stmt)) { If(!v_pResultIsNull[0]) { Printf(“Name is %s, Name length is %d”, szName, ResultLength[0]);} If(!v_pResultIsNull[1]) { Printf(“PhotoData length is %d”, ResultLength[0]); //這裡的PhotoData是二進位值,只能按長度位拷貝} } //釋放MYSQL_STMT和MYSQL對象Mysql_stmt_close(pSql_Stmt);pSql_Stmt = NULL;Mysql_close(pSql);pSql = NULL;
4、
mysql_stmt_send_long_data()函數
改函數用於將比較長的參數分幾塊依次傳輸給服務端,用法和上例一樣,只是在綁定MYSQL_BIND參數值時,調用mysql_stmt_send_long_data(),傳入BIND指向的參數每一塊指標和長度,具體可見:
http://dev.mysql.com/doc/refman/5.1/zh/apis.html#mysql-stmt-send-long-data