SQLite入门使用教程(一)



  最近在做一个C++的项目,里面用到了SQLIte数据库。于是,到官网去查看SQLite 的C++接口,因为到网上的博客去看别人写的SQLite教程,有些看不太懂,所以只好到官网上去看。其实,我还是喜欢用Qt来操作SQLite,因为Qt 对SQLite的接口函数进行了封装,操作更方便。但是项目组里的其他人用的是VS 2010,于是,不得不去看官网的英文文档。             SQLite C/C++ 接口网址:http://www.sqlite.org/cintro.html点击打开链接



      首先,只要是对数据库操作有些了解的朋友都知道:数据库操作无非就是增,删,改,查,这些基本的操作。学习SQLite之前,首先要安装好SQLite的库文件,这个大家可以去官网上下。在Linux 下安装SQLite是非常方便的,我是用新得立软件包这个软件一键安装的,在Windows下,就需要sqlite3.dll,sqlite3.h,sqlite3.lib这三个文件,分别为动态库文件,头文件和静态库文件。然后相应的进行配置,这个可以去网上查。


接下来我们就来看官网上的介绍:
(一) 核心对象和接口:
            1. 在SQLite中最核心的两个对象是,database_connection和prepared_statement。database_connection对象是由sqlite3_open()接口函数创建并返回的,它是一个数据库连接对象,在程序使用任何其他SQLite接口函数之前,必须先调用该函数以便获得database connection 对象,否则不能打开一个数据库。严格来讲,prepared statement对象不是必须的,因为有两个更为方便的包装接口: sqlite3_exec和sqlite3_get_table,这两个接口可以被方便的使用并且隐藏了 prepared statement对象。然而,对 prepared statement对象的理解对我们充分理解和使用SQLite数据库有很大的帮助。这两个接口函数在下一篇博文中讲解。


            2.在SQLite中最核心的六个接口是:
sqlite3_open();
sqlite3_prepare();
sqlite3_step();
sqlite3_column();
sqlite3_finalize();
sqlite3_close();

                                          

下面对它们的用法进行说明:

2.0    打开数据库:
int sqlite3_open(
  const char *filename,  /* Database filename (UTF-8) */待打开(创建)的数据库文件名
  sqlite3 **ppDb         /* OUT: SQLite db handle */sqlite3数据库句柄的指针
);
该接口打开一个数据库文件,并与一个sqlite3句柄关联。如果该文件不存在则创建它。返回值如果是SQLITE_OK则打开成功。

如:sqlite3 *mysqlite3;       //定义一个数据库句柄,可以理解为一个数据库连接

           sqlite3_open("D:\\mysqlite\\mysqlite.db",&mysqlite3);


2.1 创建预处理语句对象:
int sqlite3_prepare(
  sqlite3 *db,            /* Database handle */  数据库句柄
  const char *zSql,       /* SQL statement, UTF-8 encoded */  sql语句
  int nByte,              /* Maximum length of zSql in bytes. */sql语句长度,设置成-1,则自动按字符串计算sql语句长度
  sqlite3_stmt **ppStmt,  /* OUT: Statement handle */     prepared statement对象
  const char **pzTail     /* OUT: Pointer to unused portion of zSql */   一般为NULL即可
);

该接口把一个SQL语句文本转换成一个预处理语句对象并返回一个指向该对象的指针。这个接口需要一个由先前调用sqlite3_open()返回的数据库连接对象指针以及一个预处理的SQL语句文本字符串为参数。这个API并不实际解析SQL语句,仅仅是为后续的解析而对SQL语句进行的预处理。也就是说,调用sqlite3_prepare()将SQL语句编译为sqlite内部一个结构体(sqlite3_stmt),该结构体中包含了将要执行的的SQL语句的信息。

如:sqlite3_prepare_v2(mysqlite3,"select * from friends",-1,&stmt,NULL);


2.2 执行SQL语句 
int sqlite3_step(sqlite3_stmt*);
该接口用于解析一个由先前通过sqlite3_prepare()接口创建的预处理语句,直至返回第一行结果为止。通过再次调用sqlite3_step()可以返回下一行的结果,继续不断

地调用sqlite3_step()直至整个语句完成为止。对于那些并不返回结果的语句(例如:insert,delete语句等)一次调用sqlite3_step()就完成了语句的处理。注意,调用sqlite3_step()这时候SQL语句才真正执行,一次它只返回一行数据。

返回值:SQLITE_BUSY:数据库被锁,可以等待释放后重新调用该函数
       SQLITE_DONE:成功
       SQLITE_ROW:成功并且有数据返回,每查询到一条数据都会返回该值
       SQLITE_ERROR:失败
       SQLITE_MISUSE:错误的调用,比如已经返回了SQLITE_DONE或者SQLITE_ERROR后还继续调用该函数

       如:sqlite3_step(stmt);

2.3 对返回的行数据中的每一列进行查询:sqlite3_column_xxx, 其中blob,double,int,int64,text,text16表示的是要查询的那一列的数据类型

const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);//其中参数iCol为列号,从0开始,即第一列为0
int sqlite3_column_bytes(sqlite3_stmt*, int iCol);      //sqlite3_stmt* 为prepared statement对象的指针
int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
double sqlite3_column_double(sqlite3_stmt*, int iCol);
int sqlite3_column_int(sqlite3_stmt*, int iCol);
sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);   
const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
int sqlite3_column_type(sqlite3_stmt*, int iCol);
sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
 
以上接口返回一个由sqlite3_step()解析的预处理语句结果集中当前行的某一列数据。每次执行sqlite3_step()都返回一个新的结果集中的一行。可以多次调用sqlite3_column_xxx()接口返回那一行中所有列的数据。sqlite3_column_xxx是一组用于从结果集中查询出各个列项各种数据类型数据的函数接口。在这组函数接口中,有些接口返回结果集的大小,有些返回结果集的列数。

如:
int ID = sqlite3_column_int( stmt, 0 );
char * IP = sqlite3_column_text(stmt,1 );
char *name  = sqlite3_column_text( stmt, 2 );


2.4 销毁预处理语句sqlite3_finalize() 

 int sqlite3_finalize(sqlite3_stmt *pStmt); 

sqlite3_finalize()释放之前调用sqlite3_prepare()创建的预处理语句stmt占用的内存,该内存是在sqlite3_prepare()时分配的,每一个预处理语句都必须调用这个接口进行销毁以避免内存泄漏。

如:sqlite3_finalize(stmt);

2.5 关闭数据库 sqlite3_close()
int sqlite3_close(sqlite3*);
  该接口关闭一个由之前调用sqlite3_open()创建的数据库连接,所有与该连接相关的预处理语句都必须在关闭连接之前销毁。

如:sqlite3_close(mysqlite3);



下面,通过一个实例代码来演示它们的用法:


void Talk()   //根据ID号204,查询其IP为多少
{
    sqlite3 *mysqlite3;     //SQLite 连接对象
    int reopen;
    reopen = sqlite3_open("D:\\mysqlite\\mysqlite.db",&mysqlite3);//返回值如果是SQLITE_OK,则打开成功,SQLITE_OK为sqlite3.h中的宏定义
   if(reopen != SQLITE_OK )               //#define SQLITE_OK     0 /* Successful result */               {
      cout<<"it failed to open mysqlite.db"<<endl;
   }else
   {
      cout<<"it success to open mysqlite.db"<<endl;
    }
    sqlite3_stmt *stmt;//prepare_statment 对象
    char *sql="select IP from userInfo where ID = 204";   //SQL语句,表示查询ID=204所在的那行的IP那一列的数据                                                                    
    sqlite3_prepare_v2(mysqlite3,sql,-1,&stmt,NULL); //把SQL语句作为第二个参数传入,第三个参数-1      表示自动按字符串计算sql语句长度,第五个一般为NULL
    int restep = sqlite3_step(stmt)//返回值如果是SQLITE_ROW,表示成功并且有数据返回,SQLITE_ROW为sqlite3.h中的宏定义                                                         
    if(restep == SQLITE_ROW)        //#define SQLITE_ROW  100  
    {
       char *IP= (char *)sqlite3_column_text(stmt,0); //因为这里只返回IP那一列的值,所以第二个参数为0         cout << IP<<endl;
    }
    sqlite3_finalize(stmt);
    sqlite3_close(mysqlite3);
}


               通过上面的例子相信大家应该基本学会了SQLITE3的基本用法,再来分析上面的例子,相信大家会发现它的不灵活,因为它查询的ID是写死的,如果我想查询任一个ID的信息呢?那就需要把ID作为形参传入这个函数,这就是接下来要讲的:


(二)参数绑定和重新执行已编译语句

在上面的讨论中,假定每个SQL语句一旦准备,然后就执行,最后被销毁。然而,SQLite3允许相同的预处理语句执行多次。这时使用以下程序来完成:sqlite3_bind()       sqlite3_reset()

int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); //sqlite3_bind_  后面跟 着的大多是绑定的数据类型,有二进制对象,整形等
int sqlite3_bind_double(sqlite3_stmt*, int, double); //所有的这些函数第二个参数表示绑定SQL语句中的第几 个参数,
最左边的SQL参数的索引为1
int sqlite3_bind_int(sqlite3_stmt*, int, int);  //
第三个参数为绑定到占位符的值,即SQL参数的值
int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);  

int sqlite3_bind_null(sqlite3_stmt*, int);
int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);//第四个参数为参数的字节数(注意不是字符数),如 果为负,则把参数当作字符串输入

int sqlite3_reset(sqlite3_stmt *pStmt);   //第一个参数是一个指向sqlite3_stmt对象的指针

         即sqlite3_bind_XXX()函数将对应的参数传入,sqlite3_reset()来清除已经绑定的参数。当一个准备语句prepared statement)被执行通过一次或多次调用sqlite3_step ( ) ,它也可以调用sqlite3_reset ( )来重置。之所以调用sqlite3_reset()来重置而不是调用sqlite3_prepare()来重新创建,是因为可以避免不必要的消耗。通常我们很少多次执行完全相同的SQL语句,更多的时候我们可能需要执行一个相似的语句,比如插入多条数据,执行的是相似的INSERT语句,只是其中包含的参数不同,这些参数可以在语句被执行之前绑定到一个变量上,我们只需要不断的改变这个变量的值,然后执行相同的准备语句prepared statement)即可。

在SQLITE中可以使用以下几种:
  ?    
    ?NNN  
    :AAA  
    $AAA  
    @AAA  
这些参数只是代表了一个占位符,我们可以通过调用sqlite3_bind()来绑定具体的值到这个占位符上。这几个参数的具体用法与区别可以参考下面这个链接:点击打开链接http://blog.csdn.net/klarclm/article/details/7527788


下面,通过一个实例代码来演示它们的用法:还是上面那个图中的数据
void Talk(int id)                           //根据ID号这个形参,查询其IP为多少
{
sqlite3 *mysqlite3;     //SQLite 连接对象
         int reopen;
         reopen = sqlite3_open("D:\\mysqlite\\mysqlite.db",&mysqlite3);
        if(reopen != SQLITE_OK )
        {
       cout<<"it failed to open mysqlite.db"<<endl;
        }else
       {
       cout<<"it success to open mysqlite.db"<<endl;
       }
        sqlite3_stmt *stmt;//prepare_statment 对象
        char *sql="select IP from userInfo where ID = @id"; //这里用的是@AAA这个占位符,也可以用其他的几个                   
        sqlite3_prepare_v2(mysqlite3,sql,-1,&stmt,NULL);
        sqlite3_bind_int(stmt, 1, id);  //把id这个变量绑定到占位符上,我们可以通过函数的形参把具体的值传给id这个变量                 
        int restep = sqlite3_step(stmt);
        if(restep == SQLITE_ROW)    //查询IP
         {
      char *IP= (char *)sqlite3_column_text(stmt,0);
       cout << IP<<endl;
                 }
        sqlite3_finalize(stmt);
        sqlite3_close(mysqlite3);
}


         sqlite3_reset()是来清除已经绑定的参数,比较简单,这里不多讲它的用法了。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值