zoukankan      html  css  js  c++  java
  • SQLite接口函数

    SQLite核心源代码由C语言写就,同时提供了很多的扩展包可应用于其他编程语言和类库,如Python、Ruby、Java、Perl、.Net/C#、Qt和ODBC。在很多情况下,针对一种语言有很多扩展包可供选择,诸多的扩展包为不同的程序员满足不同的需求而设计开发。

    由于笔者目前从事嵌入式开发相关的工作,所以从C语言的角度对SQLite的api进行探索和实践,本文主要从实例出发,结合代码在实践中学习与理解C API的使用,关于C/C++ 接口函数更细节的部分本文不再详细赘述,请具体请参考官方文件 An Introduction To The SQLite C/C++ Interface或者《SQLite 权威指南》。

    C/C++ 接口函数概述

    数据库连接对象和SQL语句对象由下面几个核心的C/C++接口来控制:sqlite3_open()、sqlite3_prepare()、sqlite3_step()、sqlite3_column()、sqlite3_finalize()、sqlite3_close()。

    使用SQLite3时根据以上函数大概分为几个过程,这几个过程是概念上的说法,而不完全是程序运行的过程,如sqlite3_column()表示的是对查询获得一行里面的数据的列的各个操作统称,实际上在sqlite中并不存在这个函数。在SQLite提供的C/C++接口中,其中5个API属于核心接口。相比于其它数据库引擎提供的API,如OCI、MySQL API等,SQLite提供的接口易于理解和掌握。

    以上六个C/C++接口及上面的两个对象构成SQLite的核心功能。注意这些接口有些有多个版本,例如sqlite3_open()有三个独立的版本:sqlite3_open(), sqlite3_open16()和sqlite3_open_v2(),它们以稍微不同的方式完成同样的事情。sqlite3_column()代表一个家族系列:sqlite_column_int(), sqlite_column_blob()等等,用于提取结果集中各种类型的列数据。

    一个SQL数据库引擎的首要任务是执行SQL语句以获得我们想要的数据。为了完成这个任务,开发需要知道两个对象数据库连接对象sqlite3和SQL预处理语句对象sqlite3_stmt,定义如下:

         typedef struct sqlite3 sqlite3;
         typedef struct sqlite3_stmt sqlite3_stmt;

    严格地说,SQL预处理语句对象不是必需的,因为有使用方便的包装函数sqlite3_exec或sqlite3_get_table,它们封装并且隐藏了SQL语句对象。不过理解SQL语句对象能更好地使用SQLite。

    代码实践

    以下为具体的实践代码,相关总结与心得以注释的形式插入在代码,在执行代码前,请先下载SQLite源码并存储在同一路径下,按照以下方式执行编译即可:(也可将sqlite3编译成函数库再调用,具体请参照笔者另一篇文章sqlite 安装与编译)

    gcc sqlite3.c test_api.c -lpthread -ldl -o testapi -I.

    具体实践代码如下: 

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <unistd.h>
      4 #include <sqlite3.h>
      5 
      6 int main( int argc, char **argv )
      7 {
      8     sqlite3 *db;
      9     sqlite3_stmt * stmt;
     10     const char *zTail;
     11     int rc = -1;
     12     char *sql;
     13     
     14     /*1. 连接数据库*/
     15     /*int sqlite3_open(  
     16      *const char *filename,        // 数据库文件名 (UTF-8)   
     17      *sqlite3 **ppDb,            // OUT: SQLite数据库句柄
     18      *int flags,                  // 数据库文件操作标志
     19      *const char *zVfs            // 用于重写默认操作系统接口sqlite3_vfs的方法
     20      *);  
     21      */
     22     rc = sqlite3_open_v2("mysqlite.db", &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
     23     if(rc != SQLITE_OK){
     24         printf("%s
    ", sqlite3_errmsg(db));
     25     }
     26     
     27     /*2. 创建Table*/
     28     /*sqlite3_prepare_v2()将SQL语句编译为sqlite内部一个结构体(sqlite3_stmt),
     29      *该结构体中包含了将要执行的SQL语句的信息
     30      *第四个参数用来指向输入参数中下一个需要编译的SQL语句存的 SQLite statement 对象的指针
     31      *注意现在sqlite3_prepare()已经不被推荐使用了,目前官司方推荐使用sqlite3_prepare_v2()
     32      *SQLITE_API int sqlite3_prepare_v2(
     33      *sqlite3 *db,            // SQLite数据库句柄 
     34      *const char *zSql,       // SQL 语句, UTF-8 编码 
     35      *int nByte,              // zSql的字节长度 
     36      *sqlite3_stmt **ppStmt,  // OUT: sql语句句柄(statement handle) 
     37      *const char **pzTail     // OUT: 指向zSql未使用的部分
     38      *);
     39      */
     40     sql = "CREATE TABLE players ( 
    
     41             id       INTEGER PRIMARY KEY, 
    
     42             name     TEXT, 
    
     43             age     INTEGER);";
     44     rc = sqlite3_prepare_v2(db, sql, -1, &stmt, &zTail);
     45     if(rc != SQLITE_OK){
     46         printf("%s
    ", sqlite3_errmsg(db));
     47     }
     48     
     49     /*调用sqlite3_step(),此时SQL语句才真正执行,执行成功,返回SQLITE_DONE或SQLITE_ROW.
     50      *每次调用sqlite3_step(),只返回一行数据,使用sqlite3_column_XXX()函数来取出这些数据
     51      *要取出全部的数据,则需要反复调用sqlite3_step()
     52      */
     53     rc = sqlite3_step(stmt);
     54     if(rc != SQLITE_DONE){
     55         printf("%s
    ", sqlite3_errmsg(db));
     56     }
     57 
     58     /*调用sqlite3_finalize(),释放stmt占用的内存,该内存是在sqlite3_prepare()时分配的
     59      *如果SQL语句要重复使用,可以调用sqlite3_reset()来清除已经绑定的参数
     60      */
     61     rc = sqlite3_finalize(stmt);
     62     if(rc != SQLITE_OK){
     63         printf("%s
    ", sqlite3_errmsg(db));
     64     }
     65     
     66     /*3.1 插入数据*/
     67     sql = "INSERT INTO players (name,age) VALUES(?,?);";
     68     rc = sqlite3_prepare_v2(db, sql, -1, &stmt, &zTail);
     69     if(rc != SQLITE_OK){
     70         printf("%s
    ", sqlite3_errmsg(db));
     71     }
     72 
     73     /*sqlite3_bind_xxx的第四个参数为负,则字符串长度由第一个0终的位数决定
     74      *SQLITE_STATIC表示命令执行完后的信息为static类型,不能被改动,而且不需要被free
     75      */
     76     char str[] = "Kevin";
     77     int n = 23;
     78     sqlite3_bind_text(stmt,1,str,-1,SQLITE_STATIC);
     79     sqlite3_bind_int(stmt,2,n);
     80     rc = sqlite3_step(stmt);
     81     if( rc != SQLITE_DONE){
     82         printf("%s",sqlite3_errmsg(db));
     83     }
     84 
     85     //清除已经绑定的参数
     86     sqlite3_reset(stmt);
     87     //插入第二个数据
     88     char str2[] = "Jack";
     89     int n2 = 16;
     90     sqlite3_bind_text(stmt,1,str2,-1,SQLITE_STATIC);
     91     sqlite3_bind_int(stmt,2,n2);
     92     rc = sqlite3_step(stmt);
     93     if( rc != SQLITE_DONE){
     94         printf("%s",sqlite3_errmsg(db));
     95     }
     96     sqlite3_finalize(stmt); //释放stmt所占的内存
     97 
     98     /*3.2 插入数据*/
     99     char **pz_err_msg = NULL;
    100     sql = "INSERT INTO players(name, age) VALUES('Rose', 24);";
    101     rc = sqlite3_exec(db, sql, NULL, NULL, pz_err_msg);
    102     if (SQLITE_OK != rc) {
    103         printf("%s:sqlite3_exec insert "%s" failed
    ", __FUNCTION__, sql);
    104         if (NULL != pz_err_msg)    {
    105             printf("%s: error: %s
    ", __FUNCTION__, *pz_err_msg);
    106             sqlite3_free(pz_err_msg);
    107             pz_err_msg = NULL;    
    108         }
    109     }
    110 
    111     /*4. 查询所有数据*/
    112     sql = "SELECT id, name, age FROM players ORDER BY age";
    113     rc = sqlite3_prepare_v2(db, sql, -1, &stmt, &zTail);
    114     if(rc != SQLITE_OK){
    115         printf("%s
    ", sqlite3_errmsg(db));
    116     }
    117 
    118     int number, id;
    119     const unsigned char * name;
    120     /*
    121     ** 执行SQL语句之后会,sqlite3_step()会返回不同的参数,如[SQLITE_BUSY],[SQLITE_DONE], 
    122     ** [SQLITE_ROW], [SQLITE_ERROR], [SQLITE_MISUSE].
    123     ** 当该函数完成一次类似查询(select)的SQL语句执行后,将返回[SQLITE_ROW],每执行一次
    124     ** sqlite3_step(),都将准备好一行新的查询数据结果,该结果可通过sqlite3_column()系列函
    125     ** 数获取;要查询下一行的数据,只需重复执行sqlite3_step()即可。
    126      */
    127     rc = sqlite3_step(stmt);
    128     while( rc == SQLITE_ROW ){
    129         id = sqlite3_column_int( stmt, 0 );  //该函数用于获取当前行指定列(id)的数据(int类型)
    130         name = sqlite3_column_text( stmt, 1 );
    131         number = sqlite3_column_int( stmt, 2 );
    132         printf("ID: %d Name: %s Age: %d 
    ",id,name,number);
    133         sleep(1);
    134         rc = sqlite3_step(stmt);
    135     }
    136     rc = sqlite3_finalize(stmt);
    137     if(rc != SQLITE_OK){
    138         printf("%s
    ", sqlite3_errmsg(db));
    139     }
    140 
    141     /*5. 删除数据*/
    142     sql = "DELETE FROM players WHERE age < 24;";
    143     rc = sqlite3_exec(db, sql, NULL, NULL, pz_err_msg);
    144     if (SQLITE_OK != rc) {
    145         printf("%s:sqlite3_exec insert "%s" failed
    ", __FUNCTION__, sql);
    146         if (NULL != pz_err_msg)    {
    147             printf("%s: error: %s
    ", __FUNCTION__, *pz_err_msg);
    148             sqlite3_free(pz_err_msg);
    149             pz_err_msg = NULL;    
    150         }
    151     }
    152 
    153     /*6. 查询所有数据2*/
    154     int nrow = 0, ncol = 0;
    155     int i, j;
    156     char **result;
    157     sql = "SELECT id, age, name FROM players;";
    158     rc = sqlite3_get_table(db, sql, &result, &nrow, &ncol, pz_err_msg);
    159     if (SQLITE_OK != rc)
    160     {
    161         printf("%s:sqlite3_get_table "%s" failed
    ", __FUNCTION__, sql);
    162         if (NULL != pz_err_msg)
    163         {
    164             printf("%s: error: %s
    ", __FUNCTION__, *pz_err_msg);
    165             sqlite3_free(pz_err_msg);
    166             pz_err_msg = NULL;
    167         }
    168     }
    169     for(i=0; i < nrow+1; i++) {
    170         for(j=0; j < ncol; j++) {
    171             printf("%s  ", result[i * ncol + j]);
    172         }
    173         printf("
    ");
    174     }
    175 
    176     /*5. 关闭数据库*/
    177     sqlite3_close(db);
    178     return 0;
    179 }
  • 相关阅读:
    更改滚动条样式
    进度条代码
    css实现线条样式(中间高亮,两边透明)
    实现瀑布流布局 https://blog.csdn.net/csdn_zsdf/article/details/69367182
    css实现等高布局
    select多选框默认第一个是---请选择---
    后台返回的数据换行显示
    js实现文字无间断上下滚动
    用swiper实现类似淘抢购的滑动tab效果
    解决iframe高度自适应的问题
  • 原文地址:https://www.cnblogs.com/luego/p/11958090.html
Copyright © 2011-2022 走看看