關於mysql預處理:
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語句的輸入參數爲18
- v_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