1. 程式人生 > >sqlite之我見--C/C++ API介面示例 .

sqlite之我見--C/C++ API介面示例 .

在之前的兩篇博文中,分別介紹了SQLITE的基礎知識和操作,C/C++ 的一些常用API

本文中,我會給大家用幾個小程式示例SQLITE C/C++ API的使用。

1.我們看下最簡單的sqlite程式,通過sqlite3_open, sqlite3_exec, sqlite3_close來實現一個簡單的資料庫操作。

[cpp] view plaincopyprint?
  1. /*  
  2.  * File:   sqlite_test.cpp 
  3.  * Author: Carl 
  4.  * 
  5.  * Created on September 20, 2012, 3:28 PM 
  6.  */
  7. #include <cstdlib>
  8. #include <cstdio>
  9. #include <sqlite3.h>
  10. staticint _sql_callback(void *notused, int argc, char **argv, char **szColName)  
  11. {  
  12. int i = 0;  
  13.     printf("notused:0x%x, argc:%d\n", notused, argc);  
  14. for (i = 0; i < argc; i++)  
  15.     {  
  16.         printf("%s = %s\n", szColName[i], argv[i] == 0 ? "NULL"
     : argv[i]);  
  17.     }  
  18.     printf("\n");  
  19. return 0;  
  20. }  
  21. /* 
  22.  *  
  23.  */
  24. int main(int argc, char** argv)  
  25. {  
  26. constchar *sSQL1 = "create table users(userid varchar(20) PRIMARY KEY, age int, birthday datetime);";  
  27. constchar *sSQL2 = "insert into users values('wang', 20, '1989-5-4');";  
  28. constchar *sSQL3 = "select * from users;"
    ;  
  29.     sqlite3 *db = 0;  
  30. char *pErrMsg = 0;  
  31. int ret = 0;  
  32. //連線資料庫
  33.     ret = sqlite3_open("./test.db", &db);  
  34. if (ret != SQLITE_OK)  
  35.     {  
  36.         fprintf(stderr, "無法開啟資料庫:%s\n", sqlite3_errmsg(db));  
  37.         sqlite3_close(db);  
  38. return 1;  
  39.     }  
  40.     printf("資料庫連線成功\n");  
  41. //執行建表SQL
  42.     ret = sqlite3_exec(db, sSQL1, _sql_callback, 0, &pErrMsg);  
  43. if (ret != SQLITE_OK)  
  44.     {  
  45.         fprintf(stderr, "SQL create error: %s\n", pErrMsg);  
  46.         sqlite3_free(pErrMsg); //這個要的哦,要不然會記憶體洩露的哦!!!
  47.         sqlite3_close(db);  
  48. return 1;  
  49.     }  
  50.     printf("資料庫建表成功!!\n");  
  51. //執行插入資料
  52.     ret = sqlite3_exec(db, sSQL2, _sql_callback, 0, &pErrMsg);  
  53. if (ret != SQLITE_OK)  
  54.     {  
  55.         fprintf(stderr, "SQL insert error: %s\n", pErrMsg);  
  56.         sqlite3_free(pErrMsg); //這個要的哦,要不然會記憶體洩露的哦!!!
  57.         sqlite3_close(db);  
  58. return 1;  
  59.     }  
  60.     printf("資料庫插入資料成功!\n");  
  61. //執行查詢操作
  62.     ret = sqlite3_exec(db, sSQL3, _sql_callback, 0, &pErrMsg);  
  63. if (ret != SQLITE_OK)  
  64.     {  
  65.         fprintf(stderr, "SQL error: %s\n", pErrMsg);  
  66.         sqlite3_free(pErrMsg);  
  67.         sqlite3_close(db);  
  68. return 1;  
  69.     }  
  70.     printf("資料庫查詢成功!!\n");  
  71. //關閉資料庫
  72.     sqlite3_close(db);  
  73.     db = 0;  
  74. return 0;  
  75. }  
/* 
 * File:   sqlite_test.cpp
 * Author: Carl
 *
 * Created on September 20, 2012, 3:28 PM
 */

#include <cstdlib>
#include <cstdio>
#include <sqlite3.h>

static int _sql_callback(void *notused, int argc, char **argv, char **szColName)
{
    int i = 0;
    
    printf("notused:0x%x, argc:%d\n", notused, argc);
    for (i = 0; i < argc; i++)
    {
        printf("%s = %s\n", szColName[i], argv[i] == 0 ? "NULL" : argv[i]);
    }
    printf("\n");
    
    return 0;
}

/*
 * 
 */
int main(int argc, char** argv)
{
    const char *sSQL1 = "create table users(userid varchar(20) PRIMARY KEY, age int, birthday datetime);";
    const char *sSQL2 = "insert into users values('wang', 20, '1989-5-4');";
    const char *sSQL3 = "select * from users;";
    
    sqlite3 *db = 0;
    char *pErrMsg = 0;
    int ret = 0;
    
    //連線資料庫
    ret = sqlite3_open("./test.db", &db);
    if (ret != SQLITE_OK)
    {
        fprintf(stderr, "無法開啟資料庫:%s\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        return 1;
    }
    printf("資料庫連線成功\n");
    
    //執行建表SQL
    ret = sqlite3_exec(db, sSQL1, _sql_callback, 0, &pErrMsg);
    if (ret != SQLITE_OK)
    {
        fprintf(stderr, "SQL create error: %s\n", pErrMsg);
        sqlite3_free(pErrMsg); //這個要的哦,要不然會記憶體洩露的哦!!!
        sqlite3_close(db);
        return 1;
    }
    printf("資料庫建表成功!!\n");
    
    //執行插入資料
    ret = sqlite3_exec(db, sSQL2, _sql_callback, 0, &pErrMsg);
    if (ret != SQLITE_OK)
    {
        fprintf(stderr, "SQL insert error: %s\n", pErrMsg);
        sqlite3_free(pErrMsg); //這個要的哦,要不然會記憶體洩露的哦!!!
        sqlite3_close(db);
        return 1;
    }
    printf("資料庫插入資料成功!\n");
    
    //執行查詢操作
    ret = sqlite3_exec(db, sSQL3, _sql_callback, 0, &pErrMsg);
    if (ret != SQLITE_OK)
    {
        fprintf(stderr, "SQL error: %s\n", pErrMsg);
        sqlite3_free(pErrMsg);
        sqlite3_close(db);
        return 1;
    }
    printf("資料庫查詢成功!!\n");
    
    //關閉資料庫
    sqlite3_close(db);
    db = 0;
    
    return 0;
}

執行結果如下結果:

[plain] view plaincopyprint?
  1. [[email protected] sqlite]$ g++ sqlite_test.cpp -lsqlite3  
  2. [[email protected] sqlite]$ ./a.out   
  3. 資料庫連線成功  
  4. 資料庫建表成功!!  
  5. 資料庫插入資料成功!  
  6. notused:0x0, argc:3  
  7. userid = wang  
  8. age = 20  
  9. birthday = 1989-5-4  
  10. 資料庫查詢成功!!  
  11. [[email protected] sqlite]$  
[[email protected] sqlite]$ g++ sqlite_test.cpp -lsqlite3
[[email protected] sqlite]$ ./a.out 
資料庫連線成功
資料庫建表成功!!
資料庫插入資料成功!
notused:0x0, argc:3
userid = wang
age = 20
birthday = 1989-5-4

資料庫查詢成功!!
[[email protected] sqlite]$

2. 我們再看一個在sqlite上是有事務來實現原子操作的的例子,

程式碼如下:

[cpp] view plaincopyprint?
  1. /*  
  2.  * File:   sqlite_test.cpp 
  3.  * Author: Carl 
  4.  * 
  5.  * Created on 2012年9月22日, 上午7:50 
  6.  */
  7. #include <cstdlib>
  8. #include <cstdio>
  9. #include <sqlite3.h>
  10. staticint _sql_callback(void *notused, int argc, char **argv, char **szColName)  
  11. {  
  12. int i = 0;  
  13.     printf("notused:0x%x, argc:%d\n", notused, argc);  
  14. for (i = 0; i < argc; i++)  
  15.     {  
  16.         printf("%s = %s\n", szColName[i], argv[i] == 0 ? "NULL" : argv[i]);  
  17.     }  
  18.     printf("\n");  
  19. return 0;  
  20. }  
  21. /* 
  22.  *  
  23.  */
  24. int main(int argc, char** argv)  
  25. {  
  26. constchar *sSQL1 = "create table test_for_cpp (id int, name varchar(10), age int);";  
  27. char sql[100] = {0};  
  28.     sqlite3 *db = NULL;  
  29. char *pErrMsg = NULL;  
  30. int ret = 0;  
  31. bool is_success = true;  
  32. constchar *sSQL3 = "select * from test_for_cpp;";    
  33.     ret = sqlite3_open("./test.db", &db);  
  34. if (SQLITE_OK != ret)  
  35.     {  
  36.         fprintf(stderr, "無法開啟資料庫: %s\n", sqlite3_errmsg(db));  
  37.         sqlite3_close(db);  
  38. return 1;  
  39.     }  
  40.     printf("資料庫連線成功\n");    
  41.     ret = sqlite3_exec(db, sSQL1, NULL, 0, &pErrMsg);  
  42. if (SQLITE_OK != ret)  
  43.     {  
  44.         fprintf(stderr, "SQL create error: %s\n", pErrMsg);  
  45.         sqlite3_free(pErrMsg);  
  46.         sqlite3_close(db);  
  47. return 1;  
  48.     }  
  49.     printf("資料庫建表成功!!\n");    
  50.     sqlite3_exec(db, "begin;", _sql_callback, 0, &pErrMsg); //開啟事務
  51. if (SQLITE_OK != ret)  
  52.     {  
  53.         fprintf(stderr, "SQL begin error: %s\n", pErrMsg);  
  54.         sqlite3_free(pErrMsg);  
  55.         sqlite3_close(db);  
  56. return 1;  
  57.     }  
  58.     printf("資料庫開啟事務成功!!\n");    
  59. for (int i = 0; i < 10; i++)  
  60.     {  
  61.         sprintf(sql, "insert into test_for_cpp(id, name, age) values(%d, \"%s\", %d);", i, "Carl", i);  
  62.         ret = sqlite3_exec(db, sql, _sql_callback, 0, &pErrMsg);  
  63. if (SQLITE_OK != ret)  
  64.         {  
  65.             is_success = false;  
  66.             fprintf(stderr, "for %d time error: %s\n", i, pErrMsg);  
  67.             sqlite3_free(pErrMsg);  
  68. break;  
  69.         }  
  70.     }  
  71. if (is_success)  
  72.     {  
  73.         sqlite3_exec(db, "commit;", 0, 0, 0);  
  74.         printf("資料庫插入資料成功!\n");    
  75.     }  
  76. else
  77.     {  
  78.         sqlite3_exec(db, "rollback;", 0, 0, 0);  
  79.         printf("資料庫插入資料失敗!\n");    
  80.     }  
  81.     ret = sqlite3_exec(db, sSQL3, _sql_callback, 0, &pErrMsg);  
  82. if (SQLITE_OK != ret)  
  83.     {  
  84.         fprintf(stderr, "SQL ERROR: %s\n", pErrMsg);  
  85.         sqlite3_free(pErrMsg);  
  86.         sqlite3_close(db);  
  87. return 1;  
  88.     }  
  89.     printf("資料庫查詢成功!!\n");    
  90.     sqlite3_close(db);  
  91.     db = 0;  
  92. return 0;  
  93. }  
/* 
 * File:   sqlite_test.cpp
 * Author: Carl
 *
 * Created on 2012年9月22日, 上午7:50
 */

#include <cstdlib>
#include <cstdio>
#include <sqlite3.h>

static int _sql_callback(void *notused, int argc, char **argv, char **szColName)
{
    int i = 0;
    
    printf("notused:0x%x, argc:%d\n", notused, argc);
    for (i = 0; i < argc; i++)
    {
        printf("%s = %s\n", szColName[i], argv[i] == 0 ? "NULL" : argv[i]);
    }
    printf("\n");
    
    return 0;
}


/*
 * 
 */
int main(int argc, char** argv)
{
    const char *sSQL1 = "create table test_for_cpp (id int, name varchar(10), age int);";
    char sql[100] = {0};
    sqlite3 *db = NULL;
    char *pErrMsg = NULL;
    int ret = 0;
    bool is_success = true;
    const char *sSQL3 = "select * from test_for_cpp;";  
    
    ret = sqlite3_open("./test.db", &db);
    if (SQLITE_OK != ret)
    {
        fprintf(stderr, "無法開啟資料庫: %s\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        return 1;
    }
    printf("資料庫連線成功\n");  
    
    ret = sqlite3_exec(db, sSQL1, NULL, 0, &pErrMsg);
    if (SQLITE_OK != ret)
    {
        fprintf(stderr, "SQL create error: %s\n", pErrMsg);
        sqlite3_free(pErrMsg);
        sqlite3_close(db);
        return 1;
    }
    printf("資料庫建表成功!!\n");  
    
    sqlite3_exec(db, "begin;", _sql_callback, 0, &pErrMsg); //開啟事務
    if (SQLITE_OK != ret)
    {
        fprintf(stderr, "SQL begin error: %s\n", pErrMsg);
        sqlite3_free(pErrMsg);
        sqlite3_close(db);
        return 1;
    }
    printf("資料庫開啟事務成功!!\n");  
    
    for (int i = 0; i < 10; i++)
    {
        sprintf(sql, "insert into test_for_cpp(id, name, age) values(%d, \"%s\", %d);", i, "Carl", i);
        ret = sqlite3_exec(db, sql, _sql_callback, 0, &pErrMsg);
        if (SQLITE_OK != ret)
        {
            is_success = false;
            fprintf(stderr, "for %d time error: %s\n", i, pErrMsg);
            sqlite3_free(pErrMsg);
            break;
        }
    }
    
    if (is_success)
    {
        sqlite3_exec(db, "commit;", 0, 0, 0);
        printf("資料庫插入資料成功!\n");  
    }
    else
    {
        sqlite3_exec(db, "rollback;", 0, 0, 0);
        printf("資料庫插入資料失敗!\n");  
    }
    
    ret = sqlite3_exec(db, sSQL3, _sql_callback, 0, &pErrMsg);
    if (SQLITE_OK != ret)
    {
        fprintf(stderr, "SQL ERROR: %s\n", pErrMsg);
        sqlite3_free(pErrMsg);
        sqlite3_close(db);
        return 1;
    }
    printf("資料庫查詢成功!!\n");  
    
    sqlite3_close(db);
    db = 0;
    
    return 0;
}

執行結果: [plain] view plaincopyprint?
  1. [[email protected] sqlite]$ g++ sqlite_test.cpp -lsqlite3  
  2. [[email protected] sqlite]$ ./a.out   
  3. 資料庫連線成功  
  4. 資料庫建表成功!!  
  5. 資料庫開啟事務成功!!  
  6. 資料庫插入資料成功!  
  7. notused:0x0, argc:3  
  8. id = 0  
  9. name = Carl  
  10. age = 0  
  11. notused:0x0, argc:3  
  12. id = 1  
  13. name = Carl  
  14. age = 1  
  15. notused:0x0, argc:3  
  16. id = 2  
  17. name = Carl  
  18. age = 2  
  19. notused:0x0, argc:3  
  20. id = 3  
  21. name = Carl  
  22. age = 3  
  23. notused:0x0, argc:3  
  24. id = 4  
  25. name = Carl  
  26. age = 4  
  27. notused:0x0, argc:3  
  28. id = 5  
  29. name = Carl  
  30. age = 5  
  31. notused:0x0, argc:3  
  32. id = 6  
  33. name = Carl  
  34. age = 6  
  35. notused:0x0, argc:3  
  36. id = 7  
  37. name = Carl  
  38. age = 7  
  39. notused:0x0, argc:3  
  40. id = 8  
  41. name = Carl  
  42. age = 8  
  43. notused:0x0, argc:3  
  44. id = 9  
  45. name = Carl  
  46. age = 9  
  47. 資料庫查詢成功!!  
  48. [[email protected] sqlite]$   
[[email protected] sqlite]$ g++ sqlite_test.cpp -lsqlite3
[[email protected] sqlite]$ ./a.out 
資料庫連線成功
資料庫建表成功!!
資料庫開啟事務成功!!
資料庫插入資料成功!
notused:0x0, argc:3
id = 0
name = Carl
age = 0

notused:0x0, argc:3
id = 1
name = Carl
age = 1

notused:0x0, argc:3
id = 2
name = Carl
age = 2

notused:0x0, argc:3
id = 3
name = Carl
age = 3

notused:0x0, argc:3
id = 4
name = Carl
age = 4

notused:0x0, argc:3
id = 5
name = Carl
age = 5

notused:0x0, argc:3
id = 6
name = Carl
age = 6

notused:0x0, argc:3
id = 7
name = Carl
age = 7

notused:0x0, argc:3
id = 8
name = Carl
age = 8

notused:0x0, argc:3
id = 9
name = Carl
age = 9

資料庫查詢成功!!
[[email protected] sqlite]$ 

3. 我們接著看一下如何能夠更好的使用語句引數來操作sqlite資料庫,用sqlite3_prepare_v2, sqlite3_bind_*, sqlite3_step, sqlite3_column_*等介面來實現對資料庫的操作。

程式碼如下:裡面的註釋,有興趣的可以試著開啟試一下,但要記得註釋掉相關的重複功能的語句哦。

[cpp] view plaincopyprint?
  1. /*  
  2.  * File:   sqlite_test2.cpp 
  3.  * Author: Carl 
  4.  * 
  5.  * Created on September 21, 2012, 3:12 PM 
  6.  */
  7. #include <cstdlib>
  8. #include <cstdio>
  9. #include <cstring>
  10. #include <sqlite3.h>
  11. staticint _sql_callback(void *notused, int argc, char **argv, char **szColName)  
  12. {  
  13. int i = 0;  
  14.     printf("notused:0x%x, argc:%d\n", notused, argc);  
  15. for (i = 0; i < argc; i++)  
  16.     {  
  17.         printf("%s = %s\n", szColName[i], argv[i] == 0 ? "NULL" : argv[i]);  
  18.     }  
  19.     printf("\n");  
  20. return 0;  
  21. }  
  22. /* 
  23.  *  
  24.  */
  25. int main(int argc, char** argv)  
  26. {  
  27.     sqlite3 *conn = NULL;  
  28.     sqlite3_stmt *stmt = NULL;  
  29. char *err_msg = NULL;  
  30. int ret = 0;  
  31. char col_types[][10] = {"""Interger""Float""Text""Blob""NULL"};  
  32.     ret = sqlite3_open("./test.db", &conn);  
  33. if (SQLITE_OK != ret)  
  34.     {  
  35.         fprintf(stderr, "sqlite open err, %d\n", ret);  
  36. return 1;  
  37.     }  
  38.     printf("開啟資料庫成功!!!\n");  
  39. //    ret = sqlite3_prepare_v2(conn, "SELECT * FROM [test_for_cpp] WHERE [name]==:name", -1, &stmt, (const char **)&err_msg);
  40.     ret = sqlite3_prepare_v2(conn, "SELECT * FROM [test_for_cpp] WHERE [name]==?2", -1, &stmt, (constchar **)&err_msg);  
  41. if (SQLITE_OK != ret)  
  42.     {  
  43.         fprintf(stderr, "sqlite prepare error: %s\n", err_msg);  
  44.         sqlite3_free(err_msg);  
  45.         sqlite3_close(conn);  
  46. return 1;  
  47.     }  
  48. //    printf("資料庫語句物件編譯成功!!!%d\n", sqlite3_bind_parameter_index(stmt, ":name"));
  49.     printf("資料庫語句物件編譯成功!!!\n");  
  50.     ret = sqlite3_bind_text(stmt, 2, "Carl", 4, SQLITE_STATIC);  
  51. if (SQLITE_OK != ret)  
  52.     {  
  53.         fprintf(stderr, "sqlite bind error: %d\n", ret);  
  54.         sqlite3_close(conn);  
  55. return 1;  
  56.     }  
  57.     printf("資料庫語句物件bind成功!!!\n");  
  58. while (ret = sqlite3_step(stmt), ret == SQLITE_ROW)  
  59.     {  
  60. int col_count = sqlite3_column_count(stmt); //結果集中列的數量
  61.         printf("列數:%d\t", col_count);  
  62. constchar *col_0_name = sqlite3_column_name(stmt, 0); //獲取列名
  63.         printf("列名:%s\t", col_0_name);  
  64. int id = sqlite3_column_int(stmt, 0);  
  65.         printf("id值:%d\t", id);  
  66. int id_type = sqlite3_column_type(stmt, 0); //獲取列資料型別
  67.         printf("id型別:%d\t", id_type);  
  68. constchar *col_2_name = sqlite3_column_name(stmt, 2);  
  69. int age = sqlite3_column_int(stmt, 2);  
  70. int age_type = sqlite3_column_type(stmt, 2);  
  71. constchar *col_1_name = sqlite3_column_name(stmt, 1);  
  72. char name[80];  
  73.         strncpy(name, (constchar *)sqlite3_column_text(stmt, 1), 80);  
  74. int name_type = sqlite3_column_type(stmt, 1);  
  75. //列印結果
  76.         printf("col_count: %d, %s = %d(%s), %s = %s(%s), %s = %d(%s)\n",   
  77.                col_count, col_0_name, id, col_types[id_type], col_1_name, name,  
  78.                col_types[name_type], col_2_name, age, col_types[age_type]);  
  79.     }  
  80.     fprintf(stderr, "sqlite step exit with %d\n", ret);  
  81.     sqlite3_finalize(stmt);  
  82.     sqlite3_close(conn);  
  83. return 0;  
  84. }  
/* 
 * File:   sqlite_test2.cpp
 * Author: Carl
 *
 * Created on September 21, 2012, 3:12 PM
 */

#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <sqlite3.h>

static int _sql_callback(void *notused, int argc, char **argv, char **szColName)
{
    int i = 0;
    
    printf("notused:0x%x, argc:%d\n", notused, argc);
    for (i = 0; i < argc; i++)
    {
        printf("%s = %s\n", szColName[i], argv[i] == 0 ? "NULL" : argv[i]);
    }
    printf("\n");
    
    return 0;
}

/*
 * 
 */
int main(int argc, char** argv)
{
    sqlite3 *conn = NULL;
    sqlite3_stmt *stmt = NULL;
    char *err_msg = NULL;
    int ret = 0;
    
    char col_types[][10] = {"", "Interger", "Float", "Text", "Blob", "NULL"};
    
    ret = sqlite3_open("./test.db", &conn);
    if (SQLITE_OK != ret)
    {
        fprintf(stderr, "sqlite open err, %d\n", ret);
        return 1;
    }
    printf("開啟資料庫成功!!!\n");
    
//    ret = sqlite3_prepare_v2(conn, "SELECT * FROM [test_for_cpp] WHERE [name]==:name", -1, &stmt, (const char **)&err_msg);
    ret = sqlite3_prepare_v2(conn, "SELECT * FROM [test_for_cpp] WHERE [name]==?2", -1, &stmt, (const char **)&err_msg);
    if (SQLITE_OK != ret)
    {
        fprintf(stderr, "sqlite prepare error: %s\n", err_msg);
        sqlite3_free(err_msg);
        sqlite3_close(conn);
        return 1;
    }
//    printf("資料庫語句物件編譯成功!!!%d\n", sqlite3_bind_parameter_index(stmt, ":name"));
    printf("資料庫語句物件編譯成功!!!\n");
    
    ret = sqlite3_bind_text(stmt, 2, "Carl", 4, SQLITE_STATIC);
    if (SQLITE_OK != ret)
    {
        fprintf(stderr, "sqlite bind error: %d\n", ret);
        sqlite3_close(conn);
        return 1;
    }
    printf("資料庫語句物件bind成功!!!\n");
    
    while (ret = sqlite3_step(stmt), ret == SQLITE_ROW)
    {
        int col_count = sqlite3_column_count(stmt); //結果集中列的數量
        printf("列數:%d\t", col_count);
        const char *col_0_name = sqlite3_column_name(stmt, 0); //獲取列名
        printf("列名:%s\t", col_0_name);
        int id = sqlite3_column_int(stmt, 0);
        printf("id值:%d\t", id);
        int id_type = sqlite3_column_type(stmt, 0); //獲取列資料型別
        printf("id型別:%d\t", id_type);
        
        const char *col_2_name = sqlite3_column_name(stmt, 2);
        int age = sqlite3_column_int(stmt, 2);
        int age_type = sqlite3_column_type(stmt, 2);
        
        const char *col_1_name = sqlite3_column_name(stmt, 1);
        char name[80];
        strncpy(name, (const char *)sqlite3_column_text(stmt, 1), 80);
        int name_type = sqlite3_column_type(stmt, 1);
        
        //列印結果
        printf("col_count: %d, %s = %d(%s), %s = %s(%s), %s = %d(%s)\n", 
               col_count, col_0_name, id, col_types[id_type], col_1_name, name,
               col_types[name_type], col_2_name, age, col_types[age_type]);
    }
    
    fprintf(stderr, "sqlite step exit with %d\n", ret);
    sqlite3_finalize(stmt);
    sqlite3_close(conn);
    
    return 0;
}

執行結果如下:
[plain] view plaincopyprint?
  1. [[email protected] sqlite]$ g++ sqlite_test2.cpp -lsqlite3  
  2. [[email protected] sqlite]$ ./a.out   
  3. 開啟資料庫成功!!!  
  4. 資料庫語句物件編譯成功!!!  
  5. 資料庫語句物件bind成功!!!  
  6. 列數:3    列名:id   id值:0   id型別:1  col_count: 3, id = 0(Interger), name = Carl(Text), age = 0(Interger)  
  7. 列數:3    列名:id   id值:1   id型別:1  col_count: 3, id = 1(Interger), name = Carl(Text), age = 1(Interger)  
  8. 列數:3    列名:id   id值:2   id型別:1  col_count: 3, id = 2(Interger), name = Carl(Text), age = 2(Interger)  
  9. 列數:3    列名:id   id值:3   id型別:1  col_count: 3, id = 3(Interger), name = Carl(Text), age = 3(Interger)  
  10. 列數:3    列名:id   id值:4   id型別:1  col_count: 3, id = 4(Interger), name = Carl(Text), age = 4(Interger)  
  11. 列數:3    列名:id   id值:5   id型別:1  col_count: 3, id = 5(Interger), name = Carl(Text), age = 5(Interger)  
  12. 列數:3    列名:id   id值:6   id型別:1  col_count: 3, id = 6(Interger), name = Carl(Text), age = 6(Interger)  
  13. 列數:3    列名:id   id值:7   id型別:1  col_count: 3, id = 7(Interger), name = Carl(Text), age = 7(Interger)  
  14. 列數:3    列名:id   id值:8   id型別:1  col_count: 3, id = 8(Interger), name = Carl(Text), age = 8(Interger)  
  15. 列數:3    列名:id   id值:9   id型別:1  col_count: 3, id = 9(Interger), name = Carl(Text), age = 9(Interger)  
  16. sqlite step exit with 101 //101意思為SQLITE_DONE  
  17. [[email protected] sqlite]$   
[[email protected] sqlite]$ g++ sqlite_test2.cpp -lsqlite3
[[email protected] sqlite]$ ./a.out 
開啟資料庫成功!!!
資料庫語句物件編譯成功!!!
資料庫語句物件bind成功!!!
列數:3	列名:id	id值:0	id型別:1	col_count: 3, id = 0(Interger), name = Carl(Text), age = 0(Interger)
列數:3	列名:id	id值:1	id型別:1	col_count: 3, id = 1(Interger), name = Carl(Text), age = 1(Interger)
列數:3	列名:id	id值:2	id型別:1	col_count: 3, id = 2(Interger), name = Carl(Text), age = 2(Interger)
列數:3	列名:id	id值:3	id型別:1	col_count: 3, id = 3(Interger), name = Carl(Text), age = 3(Interger)
列數:3	列名:id	id值:4	id型別:1	col_count: 3, id = 4(Interger), name = Carl(Text), age = 4(Interger)
列數:3	列名:id	id值:5	id型別:1	col_count: 3, id = 5(Interger), name = Carl(Text), age = 5(Interger)
列數:3	列名:id	id值:6	id型別:1	col_count: 3, id = 6(Interger), name = Carl(Text), age = 6(Interger)
列數:3	列名:id	id值:7	id型別:1	col_count: 3, id = 7(Interger), name = Carl(Text), age = 7(Interger)
列數:3	列名:id	id值:8	id型別:1	col_count: 3, id = 8(Interger), name = Carl(Text), age = 8(Interger)
列數:3	列名:id	id值:9	id型別:1	col_count: 3, id = 9(Interger), name = Carl(Text), age = 9(Interger)
sqlite step exit with 101 //101意思為SQLITE_DONE
[[email protected] sqlite]$ 

下面解釋下為什麼要學會這種能夠細緻控制sqlite的方法(即使用語句引數),主要有以下幾個優點:

(1) 使用“語句引數”方式,具有更高的安全性,可以有效防止“SQL注入攻擊”。 “SQL注入攻擊”要想達到目的,就必須讓attack value隨著SQL命令字串一起傳送進SQL解析器。黑客如果在一條SQL命令字串被送入到sqlite3_prepare函式之前,利用c字串處理函式等途徑將attack value注入其中,而在sqlite3_prepare函式之中進行解析(parse),就可以達到攻擊目的。而使用“語句引數”方式,被傳送到sqlite3_prepare函式的只是SQL命令字串中的引數符號(如:“?”),而不是具體的值。在sqlite3_prepare函式執行之後,才會使用bind函式給引數符號繫結具體的值,這就可以避免attack value隨著SQL命令字串一起在sqlite3_prepare函式中被解析,從而有效躲避“SQL注入攻擊”。
(2)使用“語句引數”方式,可以更快的完成值替換。

(3)使用“語句引數”方式,更節省記憶體。原因是使用如snprintf函式,需要一個SQL命令模板,一塊足夠大的輸出快取,而且字串處理函式需要工作記憶體(working memory),除此之外對於整形,浮點型,特別是BLOBs,經常會佔用更多的空間。

水平有限,如果有朋友發現錯誤,歡迎留言交流。
轉載請保留本文連結,如果覺得我的文章能幫到您,請頂一下。,謝謝。

相關推薦

sqlite我見--C/C++ API介面示例 .

在之前的兩篇博文中,分別介紹了SQLITE的基礎知識和操作,C/C++ 的一些常用API 本文中,我會給大家用幾個小程式示例SQLITE C/C++ API的使用。 1.我們看下最簡單的sqlite程式,通過sqlite3_open, sqlite3_exec, sq

Mysql的C語言API介面在專案中的使用

#include "Mysql.h" int Mysql::select_user_store(char *sql,char *user_info) { int reta = mysql_real_query1(sql); if (

MySQL資料庫使用——MySQL在C/C++的API介面

直接操作MySQL,輸入命令效率低,將MySQL嵌入程式中,封裝介面,讓程式去訪問MySQL,才能最大效益利用MySQL。 MySQL C API移植 包含MySQL的工程檔案不應直接關聯電腦已安裝的MySQL,因為不同電腦伺服器安裝的位置不一樣,每次

TensorFlowdeeplab語義分割API介面除錯

在之前的文章中,對tensorflow目標檢測API進行了詳細的測試,成功應用其模型做簡單的檢測任務。本文對另一模組DeepLab的API進行測試,實現語義分割。 經過了好幾天的吐血折騰,終於將該模組調通,其中的bug真是數不勝數…… 1 檔案結構 首先在research/deepl

新浪短連結API介面示例

/* * 生成新浪的短連結或還原新浪短連結 */ class SinaUrl{ //新浪APPKEY const APPKEY='31641035'; //CURL private static function CURLQueryStr

SQLite - C/C++介面 API(二)

  1、開啟資料庫 SQLITE_API int sqlite3_open16(   const void *filename, /* Database filename (UTF-16) */   sqlite3 **ppDb /* OUT: SQLite db handle */);SQLI

sqliteC/C++ API介面的基礎操作與事務

一、C/C++ 介面 API 主要通過通過sqlite3_open,sqlite3_exec和qlite3_close來實現一個簡單的資料庫操作。 1.1、sqlite3_open sqlite3_open(const char *filename, sqlit

sqlite學習筆記7:C語言中使用sqlite打開數據庫

實例 clas details code 返回 pri san filename stdlib.h 數據庫的基本內容前面都已經說得差點兒相同了。接下看看如何在C語言中使用sqlite。 一 接口 sqlite3_open(const char *filename, s

sqlite學習筆記11:C語言中使用sqlite刪除記錄

false done mta ase rom real not null -a ubun 最後一節,這裏記錄下怎樣刪除數據。 前面全部的代碼都繼承在這裏了,在Ubuntu14.04和Mac10.9上親測通過。 #include <stdio.h> #in

sqlite學習筆記9:C語言中使用sqlite插入數據

name article void num mes cut cpp content int 前面創建了一張表,如今給他插入一些數據。插入數據跟創建表差點兒相同,不過SQL語言不一樣而已,完整代碼例如以下: #include <stdio.h> #inclu

SQLite - C/C++接口 API(二)

mage std per src argc sele pdb face module to 1、打開數據庫 SQLITE_API int sqlite3_open16(   const void *filename, /* Database filename (U

Zookeeper C API應用示例(3)——配置管理(非同步API

場景描述同:https://blog.csdn.net/qq_41688455/article/details/83780854 服務端程式碼如下: #include <stdio.h> #include <unistd.h> #include <std

Zookeeper C API應用示例(1)——配置管理(同步API

場景描述 服務端監控/configure目錄; 客戶端對/configure目錄讀/寫資料,建立/刪除子節點 服務端: 監控/configure目錄,有資料更新時,輸出/configure中的資料;子節點建立/刪除時,服務程式列出當前的子目錄列表。 程式碼如下: #include &

Java呼叫C++ API完整示例(dll)

最近有一個和香港的對接專案。在通訊問題上出現了卡殼。港方提供的是一個java庫,需要和我們這邊進行交易策略對接。交易策略是以協議的方式,通過網路通訊傳送到我們的系統。由於我們缺少穩定可靠的java通訊元件,但我們具有一個非常可靠的C++通訊元件。因此就萌發了將現有的C++通訊元件封裝為可供

C#基礎 二十 設計模式簡單工廠模式及介面

前言       這幾天看了這些視訊進行了一些總結,我是打算先看完C#視訊然後繼續看設計模式這本書的,但是視訊中提到了一部分設計模式中的內容,那麼我也多少的總結一下吧,有助於後邊對設計模式的學習! 交流與互動

C語言我見-02-建立第一個C程式

1.建立第一個C程式 #include<stdio.h> int main() { printf(“Hello CSDN!\n”); return 0; } 個人理解: 大多數人學習C語言的寫的第一個程式無外乎就是經典的“Hello World!”

PC軟體開發技術三:C#操作SQLite資料庫

我們在開發應用是經常會需要用到一些資料的儲存,儲存的方式有多種,使用資料庫是一種比較受大家歡迎的方式。但是對於一些小型的應用,如一些移動APP,通常的資料庫過於龐大,而輕便的SQLite則能解決這一問題。不但操作方便,而且只需要要一個檔案即可,在這裡我們來說一說使用C#語言操作SQLite資料庫

MySQL入門常用C語言API

MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket,

C# 微信介面推送模版訊息

public string SendTempletMessge() { string strReturn = string.Empty; try { #region 獲取access_token

程式設計C#控制檯輸出日曆示例

        本題目的最終要就是根據使用者輸入的年和月在控制檯輸出單月的日曆資訊,附加範圍年在1900-2100之間,月的範圍在1-12之間,當用戶輸入不在範圍時要給予錯誤資訊提示;已知條件是1900年1月1日為星期一。         要輸出此日曆就需要知道該月的第一天