sqlite3_mprintf
- sqlite3_mprintf()函數原型:
-
char *sqlite3_mprintf(const char*,...);
- sqlite3_mprintf()的作用是將結果寫入到sqlite3_malloc()獲取的內存中,例程返回的字符串應該使用sqlite3_free()進行釋放,如果無法申請到足夠的內存,則會返回NULL指針;
- 它同c庫函數 sprintf()類似,實現一些額外的格式化。對所有常用的printf()格式化選項都適用。另外還有非常用選項:%q, %Q, %z;
- %q選項的作用類似於%s,它會替換了參數列表中以空字符結尾的字符串%q,同時他會將單引號字符轉義,有助於防止SQL注入攻擊;
- 示例:
-
char * zText =“這是快樂的一天!”; char * zSQL = sqlite3_mprintf(“INSERT INTO table VALUES('%q')”,zText); sqlite3_exec(db,zSQL,0,0,0); sqlite3_free(ZSQL)
- 因為使用了%q格式字符串,所以zText中的'\''字符被轉義,生成的SQL如下所示:
-
INSERT INTO table1 VALUES('這是快樂的一天!')
- 作為一般規則,在將文本插入字符串文字時,應始終使用%q而不是%s。
- %Q選項的作用類似於%q,除了它還在整個字符串的外部添加單引號。此外,如果參數列表中的參數是NULL指針,則%Q替換文本“NULL”(不帶單引號);
-
char * zSQL = sqlite3_mprintf(“INSERT INTO table VALUES(%Q)”,zText); sqlite3_exec(db,zSQL,0,0,0); sqlite3_free(ZSQL);
- 即使zText變量是NULL指針,上面的代碼也會在zSQL變量中呈現正確的SQL語句。
- “%z”格式化選項的作用類似於“%s”,但添加了在讀取字符串並將其復制到結果中之后,在輸入字符串上調用sqlite3_free()。
從程序看 %s, %q, %Q之間的區別
-
char *str_he = "合"; char *str_fen = "分"; //初始化表 for(rc = 0; rc < 16; rc++) { sql = sqlite3_mprintf("INSERT INTO RELAY VALUES ('%d', '%s','%s', '2019-7-12');", rc, str_he, str_fen); sqlite3_exec(db, sql, 0, 0, &zErrMsg); } rc = sqlite3_get_table(db, "SELECT * FROM RELAY", &dbresult, &nRow, &nColum, &zErrMsg); if(rc == SQLITE_OK) { index = nColum; for(i = 0; i < nRow; i++) { for(j = 0; j < nColum; j++) { printf("%d--%s : %s\n", i, dbresult[j], dbresult[index++]); // ++index; } printf("----------------------------------------------\n"); } }
- 輸出結果:
-
0--ID : 0 0--C_STATUS : 合 0--W_STATUS : 分 0--TIME : 2019-7-12 ---------------------------------------------- 1--ID : 1 1--C_STATUS : 合 1--W_STATUS : 分 1--TIME : 2019-7-12 ---------------------------------------------- 2--ID : 2 2--C_STATUS : 合 2--W_STATUS : 分 2--TIME : 2019-7-12 ---------------------------------------------- 。。。。。
- 將 %s 改為 %q ,輸出結果:
-
0--ID : 0 0--C_STATUS : 合 0--W_STATUS : 分 0--TIME : 2019-7-12 ---------------------------------------------- 1--ID : 1 1--C_STATUS : 合 1--W_STATUS : 分 1--TIME : 2019-7-12 ---------------------------------------------- 2--ID : 2 2--C_STATUS : 合 2--W_STATUS : 分 2--TIME : 2019-7-12 ----------------------------------------------
。。。。。。
- 將 %s 改為 %Q,輸出結果:
-
0--ID : 0 0--C_STATUS : 合 0--W_STATUS : 分 0--TIME : 2019-7-12 ---------------------------------------------- 1--ID : 1 1--C_STATUS : 合 1--W_STATUS : 分 1--TIME : 2019-7-12 ---------------------------------------------- 2--ID : 2 2--C_STATUS : 合 2--W_STATUS : 分 2--TIME : 2019-7-12 ---------------------------------------------- 。。。。。。
- 從上面的結果來看,當插入的字符串不為空指針時,三者之間並沒有多大差別。
- 將字符串設置為NULL
-
char *str_he = NULL; char *str_fen = NULL;
- %s 輸出結果
-
0--ID : 0 0--C_STATUS : 0--W_STATUS : 0--TIME : 2019-7-12 ---------------------------------------------- 1--ID : 1 1--C_STATUS : 1--W_STATUS : 1--TIME : 2019-7-12 ---------------------------------------------- 2--ID : 2 2--C_STATUS : 2--W_STATUS : 2--TIME : 2019-7-12 ---------------------------------------------- 。。。。。。
- %q 輸出結果
-
0--ID : 0 0--C_STATUS : (NULL) 0--W_STATUS : (NULL) 0--TIME : 2019-7-12 ---------------------------------------------- 1--ID : 1 1--C_STATUS : (NULL) 1--W_STATUS : (NULL) 1--TIME : 2019-7-12 ---------------------------------------------- 2--ID : 2 2--C_STATUS : (NULL) 2--W_STATUS : (NULL) 2--TIME : 2019-7-12 ---------------------------------------------- 。。。。。。
- %Q輸出結果
-
0--ID : 0 0--C_STATUS : (null) 0--W_STATUS : (null) 0--TIME : 2019-7-12 ---------------------------------------------- 1--ID : 1 1--C_STATUS : (null) 1--W_STATUS : (null) 1--TIME : 2019-7-12 ---------------------------------------------- 2--ID : 2 2--C_STATUS : (null) 2--W_STATUS : (null) 2--TIME : 2019-7-12 ---------------------------------------------- 。。。。。。
- 當需要插入的字符為NULL時,%s 並沒有將NULL插入到表中,但是%q, %Q能夠將NULL插入到表中,只是大小寫不一樣;