深入SQLite基本操作的总结详解

sqlite提供的是一些C函数接口,你可以用这些函数操作数据库。通过使用这些接口,传递一些标准 sql 语句(以 char * 类型)给 sqlite 函数,sqlite 就会为你操作数据库。sqlite 跟MS的access一样是文件型数据库,就是说,一个数据库就是一个文件,此数据库里可以建立很多的表,可以建立索引、触发器等等,但是,它实际上得到的就是一个文件。备份这个文件就备份了整个数据库。 sqlite 不需要任何数据库引擎,这意味着如果你需要 sqlite 来保存一些用户数据,甚至都不需要安装数据库。

下面开始介绍数据库基本操作。
1、基本流程
(1)关键数据结构:
     sqlite 里最常用到的是 sqlite3 * 类型。从数据库打开开始,sqlite就要为这个类型准备好内存,直到数据库关闭,整个过程都需要用到这个类型。当数据库打开时开始,这个类型的变量就代表了你要操作的数据库。下面再详细介绍。
(2)打开数据库:
     int sqlite3_open( 文件名, sqlite3 ** ); 用这个函数开始数据库操作。需要传入两个参数,一是数据库文件名,比如:..\\test\\testDatabase.db。
文件名不需要一定存在,如果此文件不存在,sqlite 会自动建立它。如果它存在,就尝试把它当数据库文件来打开。 其中sqlite3 ** 参数即前面提到的关键数据结构。这个结构底层细节如何,你不要关它。
    函数返回值表示操作是否正确,如果是 SQLITE_OK 则表示操作正常。相关的返回值sqlite定义了一些宏。具体这些宏的含义可以参考 sqlite3.h 文件。里面有详细定义。
(3)关闭数据库:
    int sqlite3_close(sqlite3 *); 前面如果用 sqlite3_open 开启了一个数据库,结尾时不要忘了用这个函数关闭数据库。
    sqlite数据库操作例子


代码如下:

#include "./sqlite3.h"
    int main( int , char** )
    {
        sqlite3 * db = NULL; //声明sqlite关键结构指针
        int result;
        //需要传入 db 这个指针的指针,
        //因为 sqlite3_open 函数要为这个指针分配内存,还要让db指针指向这个内存区
        result = sqlite3_open("..\\test\\testDatabase.db", &db);//打开数据库
        if( result != SQLITE_OK )
        {
            return -1; //数据库打开失败
        }
        //数据库操作代码
        //…-
        //数据库打开成功
        sqlite3_close( db ); //关闭数据库
        return 0;
    }

这就是一次数据库操作过程。

2、 SQL语句操作(如何用sqlite 执行标准 sql 语法)
(1)执行sql语句: int sqlite3_exec(sqlite3*, const char *sql, sqlite3_callback, void *, char **errmsg ); 这就是执行一条 sql 语句的函数。
 参数说明:
     第1个参数不再说了,是前面open函数得到的指针。说了是关键数据结构。
     第2个参数const char *sql 是一条 sql 语句,以\0结尾。
     第3个参数sqlite3_callback 是回调,当这条语句执行之后,sqlite3会去调用你提供的这个函数。
     第4个参数void * 是你所提供的指针,你可以传递任何一个指针参数到这里,这个参数最终会传到回调函数里面,如果不需要传递指针给回调函数,可以填NULL。等下我们再看回调函数的写法,以及这个参数的使用。
     第5个参数char ** errmsg 是错误信息。注意是指针的指针。sqlite3里面有很多固定的错误信息。执行 sqlite3_exec 之后,执行失败时可以查阅这个指针(直接 printf("%s\n",errmsg))得到一串字符串信息,这串信息告诉你错在什么地方。sqlite3_exec函数通过修改你传入的指针的指针,把你提供的指针指向错误提示信息,这样sqlite3_exec函数外面就可以通过这个 char*得到具体错误提示。
      说明:通常,sqlite3_callback 和它后面的 void * 这两个位置都可以填 NULL。填NULL表示你不需要回调。比如你做 insert 操作,做 delete 操作,就没有必要使用回调。而当你做 select 时,就要使用回调,因为 sqlite3 把数据查出来,得通过回调告诉你查出了什么数据。
(2)exec 的回调 :typedef int (*sqlite3_callback)(void*,int,char**, char**); 你的回调函数必须定义成上面这个函数的类型。

sqlite数据库操作例子:


代码如下:

//sqlite3的回调函数
     // sqlite 每查到一条记录,就调用一次这个回调
     //para是你在 sqlite3_exec 里传入的 void * 参数
     //通过para参数,你可以传入一些特殊的指针(比如类指针、结构指针),然后在这里面强制转换成对应的类型
     //(这里面是void*类型,必须强制转换成你的类型才可用)。然后操作这些数据
     //n_column是这一条记录有多少个字段 (即这条记录有多少列)
     //char ** column_value 是关键值,查出来的数据都保存在这里,实际上是个1维数组(不要以为是2维数组),
     //每一个元素都是一个 char * 值,是一个字段内容(用字符串来表示,以\0结尾)
     //char ** column_name 跟 column_value是对应的,表示这个字段的字段名称     
      int LoadMyInfo( void * para, int n_column, char ** column_value, char ** column_name )
      {
            //这里,我不使用 para 参数。忽略它的存在.
            int i;
            printf( "记录包含 %d 个字段\n", n_column );
            for( i = 0 ; i < n_column; i ++ )
            {
                printf( "字段名:%s ?> 字段值:%s\n", column_name[i], column_value[i] );
            }
            printf( "\n" );
            return 0;
      }

int main( int , char ** )
      {
            sqlite3 * db;
            int result;
            char * errmsg = NULL;
            result = sqlite3_open("..\\test\\testDatabase.db", &db );
            if( result != SQLITE_OK )
            {
                return -1; //数据库打开失败
            }
            //数据库操作代码
            //创建测试表,表名叫 MyTable_1,有2个字段: ID 和 name。其中ID是一个自动增加的类型,
            //以后insert时可以不去指定这个字段,它会自己从0开始增加            
            result = sqlite3_exec( db, "create table MyTable_1( ID integer primary key autoincrement, name nvarchar(32) ))", NULL, NULL, errmsg );
            if(result != SQLITE_OK )
            {
               printf("创建表失败,错误码:%d,错误原因:%s\n", result, errmsg );
            }
            //插入一些记录
            result = sqlite3_exec( db, "insert into MyTable_1( name) values ('走路')", 0, 0, errmsg); 
            if(result != SQLITE_OK )
          {
             printf( “插入记录失败,错误码:%d,错误原因:%s\n”, result, errmsg );
           }

result = sqlite3_exec( db,"insert into MyTable_1( name ) values ('骑单车')", 0, 0, errmsg);
            if(result != SQLITE_OK )
            {
                printf("插入记录失败,错误码:%d,错误原因:%s\n", result, errmsg );
            }

result = sqlite3_exec( db, "insert into MyTable_1( name ) values ( '坐汽车')", 0, 0, errmsg );
            if(result != SQLITE_OK )
            {
                printf( "插入记录失败,错误码:%d,错误原因:%s\n", result, errmsg );
            }             
            result = sqlite3_exec( db, "select * from MyTable_1", LoadMyInfo, NULL, errmsg );//开始查询数据库              sqlite3_close( db ); //关闭数据库            
            return 0;
      }

通过上面的例子,应该可以知道如何打开一个数据库,如何做数据库基本操作。
(3)不使用回调查询数据库
     sqlite3_exec 是使用回调来执行 select 操作。还有一个方法可以直接查询而不需要回调。但是,我个人感觉还是回调好,因为代码可以更加整齐,只不过用回调很麻烦,你得声明一个函数,如果这个函数是类成员函数,你还不得不把它声明成 static 的(C++成员函数实际上隐藏了一个参数:this,C++调用类的成员函数的时候,隐含把类指针当成函数的第一个参数传递进去。结果,这造成跟前面说的 sqlite 回调函数的参数不相符。只有当把成员函数声明成 static 时,它才没有多余的隐含的this参数)。虽然回调显得代码整齐,但有时候你还是想要非回调的 select 查询。这可以通过 sqlite3_get_table 函数做到。
    int sqlite3_get_table(sqlite3*, const char *sql, char ***resultp, int *nrow, int *ncolumn, char **errmsg );
    参数说明:
    第1个参数不再多说,看前面的例子。
    第2个参数是 sql 语句,跟 sqlite3_exec 里的 sql 是一样的。是一个很普通的以\0结尾的char *字符串。
    第3个参数是查询结果,它依然一维数组(不要以为是二维数组,更不要以为是三维数组)。它内存布局是:第一行是字段名称,后面是紧接着是每个字段的值。下面用例子来说事。
    第4个参数是查询出多少条记录(即查出多少行)。
    第5个参数是多少个字段(多少列)。
    第6个参数是错误信息,跟前面一样,这里不多说了。
sqlite数据库操作例子:


代码如下:

int main( int , char ** )
    {
        sqlite3* db;
        int result;
        char* errmsg = NULL;
        char **dbResult; //是 char ** 类型,两个*号
        int nRow, nColumn;
        int i , j;
        int index;
        result = sqlite3_open("..\\test\\testDatabase.db", &db );
        if( result != SQLITE_OK )
        {
           return -1; //数据库打开失败
        }
        //数据库操作代码
        //假设前面已经创建了 MyTable_1 表
        //开始查询,传入的 dbResult 已经是 char **,这里又加了一个 & 取地址符,传递进去的就成了 char ***
         result = sqlite3_get_table( db, "select * from MyTable_1", &dbResult, &nRow, &nColumn, &errmsg );
        if( SQLITE_OK == result ) //查询成功
        {
           index = nColumn; //前面说过 dbResult 前面第一行数据是字段名称,从 nColumn 索引开始才是真正的数据
           printf("查到%d条记录\n", nRow );
           for( i = 0; i < nRow ; i++ )
           {
               printf( "第 %d 条记录\n", i+1 );
               for( j = 0 ; j < nColumn; j++ )
               {
                 printf("字段名:%s ß> 字段值:%s\n", dbResult[j], dbResult [index]);
                 // dbResult 的字段值是连续的,从第0索引到第 nColumn - 1索引都是字段名称
                 // 从第 nColumn 索引开始,后面都是字段值,
                 //它把一个二维的表(传统的行列表示法)用一个扁平的形式来表示
                  ++index;
              }
              printf( "\n" );
          }
       }
       //到这里,不论数据库查询是否成功,都释放 char** 查询结果,使用 sqlite 提供的功能来释放
       sqlite3_free_table( dbResult );
       sqlite3_close( db );//关闭数据库
       return 0;
    }

到这个例子为止,sqlite3 的常用用法都介绍完了。 用以上的方法,完全可以应付绝大多数数据库需求。

3、事务处理
sqlite 是支持事务处理的。如果你知道你要同步删除很多数据,不仿把它们做成一个统一的事务。通常一次 sqlite3_exec 就是一次事务,如果你要删除1万条数据,sqlite就做了1万次:开始新事务->删除一条数据->提交事务->开始新事务->… 的过程。这个操作是很慢的。因为时间都花在了开始事务、提交事务上。你可以把这些同类操作做成一个事务,这样如果操作错误,还能够回滚事务。事务的操作没有特别的接口函数,它就是一个普通的 sql 语句而已:
分别如下:


代码如下:

int result;
    result = sqlite3_exec( db, "begin transaction", 0, 0, &zErrorMsg ); //开始一个事务
    result = sqlite3_exec( db, "commit transaction", 0, 0, &zErrorMsg ); //提交事务
    result = sqlite3_exec( db, "rollback transaction", 0, 0, &zErrorMsg ); //回滚事务

(0)

相关推荐

  • SQLite3中自增主键相关知识总结

    一.SQLite清空表并将自增列归零 SQL标准中有TRUNCATE TABLE语句,用来清空表的所有内容.但SQLite不支持这个语句.在SQLite中直接使用 DELETE FROM TableName 就可以了.对于大多数DBMS来说,用DELETE不如用TRUNCATE 速度快,因为TRUNCATE 不用访问整个表,不用记录数据的变动. SQLite虽然不支持TRUNCATE,但它对DELETE做了优化:通常在清空表的时候,还需要把自增列归零.在SQLite中定义自增列的方法如下: 复制

  • 深入SQLite多线程的使用总结详解

    SQLite支持3种线程模式: 单线程:这种模式下,没有进行互斥,多线程使用不安全.禁用所有的mutex锁,并发使用时会出错.当SQLite编译时加了SQLITE_THREADSAFE=0参数,或者在初始化SQLite前调用sqlite3_config(SQLITE_CONFIG_SINGLETHREAD)时启用. 多线程:这种模式下,只要一个数据库连接不被多个线程同时使用就是安全的.源码中是启用bCoreMutex,禁用bFullMutex.实际上就是禁用数据库连接和prepared stat

  • SQLITE3 使用总结

    前序: 这里要注明,我是一个跨平台专注者,并不喜欢只用 windows 平台.我以前的工作就是为 unix 平台写代码.下面我所写的东西,虽然没有验证,但是我已尽量不使用任何 windows 的东西,只使用标准 C 或标准C++.但是,我没有尝试过在别的系统.别的编译器下编译,因此下面的叙述如果不正确,则留待以后修改. 下面我的代码仍然用 VC 编写,因为我觉得VC是一个很不错的IDE,可以加快代码编写速度(例如配合 Vassist ).下面我所说的编译环境,是VC2003.如果读者觉得自己习惯

  • 浅谈SQLite时间函数的使用说明与总结分析

    本文主要讲解SQLite中时间函数进行分析与总结并给出使用案例.本文给出的例子都是经过测试.SQLite时间/日期函数种类:1.datetime():产生日期和时间2.date():产生日期3:.time():产生时间4.strftime():对以上三个函数产生的日期和时间进行格式化 SQLite时间/日期函数用法:1.datetime()的用法是:datetime(日期/时间,修正符,修正符...)2.date()和time()的语法与datetime()相同.3.strftime()函数可以

  • 解析SQLite中的常见问题与总结详解

    1. 创建数据如果不往数据库里面添加任何的表,这个数据库等于没有建立,不会在硬盘上产生任何文件,如果数据库已经存在,则会打开这个数据库. 2. 如何通过sqlite3.dll与sqlite3.def生成sqlite3.lib文件LIB /DEF:sqlite3.def /machine:IX86 3. sqlite3_open打开一个数据库时,如果数据库不存在就会新生成一个数据库文件.如果接着执行其他查询语句就会失败,比如sqlite3_prepare,编程中出现明明指定了数据库而且里面也有数据

  • 深入SQLite基本操作的总结详解

    sqlite提供的是一些C函数接口,你可以用这些函数操作数据库.通过使用这些接口,传递一些标准 sql 语句(以 char * 类型)给 sqlite 函数,sqlite 就会为你操作数据库.sqlite 跟MS的access一样是文件型数据库,就是说,一个数据库就是一个文件,此数据库里可以建立很多的表,可以建立索引.触发器等等,但是,它实际上得到的就是一个文件.备份这个文件就备份了整个数据库. sqlite 不需要任何数据库引擎,这意味着如果你需要 sqlite 来保存一些用户数据,甚至都不需

  • IOS开发中NSURL的基本操作及用法详解

    NSURL其实就是我们在浏览器上看到的网站地址,这不就是一个字符串么,为什么还要在写一个NSURL呢,主要是因为网站地址的字符串都比较复杂,包括很多请求参数,这样在请求过程中需要解析出来每个部门,所以封装一个NSURL,操作很方便. 1.URL URL是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址.互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它. URL可能包含远程服务器上的资源的位置,本地磁盘上的文件的路径,甚

  • C语言实现顺序表的基本操作的示例详解

    目录 一.认识顺序表 1.线性表 2.顺序表的概念及结构 二.顺序表的基本操作(接口实现) 1.初始化顺序表 2.打印顺序表 3.尾插 4.尾删 5.扩容 6.头插 7.头删 8.任意位置插入 9.任意位置删除 10.查找某个数的位置 三.顺序表演示及代码(含源码) 1.演示效果 2.完整源代码 一.认识顺序表 1.线性表 线性表是n个具有相同特性的数据元素的有限序列,线性表是一种在实际中广泛使用的数据结构,常见的线性表有顺序表.链表.栈.队列.字符串……线性表在逻辑上是线性结构,也就是说是一条

  • C语言中单链表(不带头结点)基本操作的实现详解

    目录 一.单链表的概念 二.单链表的基本操作 1.创建单个结点 2.创建具有n个结点的链表 3.打印单链表 4.尾插 5.尾删 6.头插 7.头删 8.查找某个结点 9.在某个结点后面插入 10.在某个结点前面插入 11.删除某个位置后面的结点 12.删除某个结点 13.销毁单链表 三.测试代码 通过对顺序表的学习,我们可以发现顺序表有以下几点缺陷: 1.空间不够时需要扩容,扩容尤其是用realloc进行异地扩容时,是有一定代价的,其次还可能存在一定空间浪费. 2.头部或者中间插入删除,需要挪动

  • C语言中带头双向循环链表基本操作的实现详解

    目录 一.概念与结构 二.基本操作的实现 1.创建结点 2.初始化链表 3.打印链表 4.尾插 5.尾删 6.头插 7.头删 8.查找某个数并返回其指针 9.在某个位置之前插入 10.删除某个位置 11.判断链表是否为空 12.计算链表中有效值的个数 13.销毁链表 三.测试代码 一.概念与结构 无头单向非循环链表结构简单,一般不会单独用来存数据.实际中更多的是作为其他数据结构的子结构,如哈希桶.图的邻接表等等.而带头双向循环链表的结构较为复杂,一般用在单独存储数据.实际中使用的链表数据结构,都

  • C++语言io流处理基本操作教程示例详解

    目录 一.输入输出流对象 流对象常用的处理函数 流控制字符 二.字符流操作 sstream 三. 文件流流类 四.文件指针定位 一.输入输出流对象 cout:标准输出流 cerr:标准出凑  和cout(只是用于如果是错误时要输出的) cin  :   标准输入 流对象常用的处理函数 输出字符 put() 输入字符:get() 输出字符串:write() 输入字符串getline() char ch; cin.get(ch); cout << ch<<endl; cout.put(

  • Python操作SQLite数据库的方法详解

    本文实例讲述了Python操作SQLite数据库的方法.分享给大家供大家参考,具体如下: SQLite简单介绍 SQLite数据库是一款非常小巧的嵌入式开源数据库软件,也就是说没有独立的维护进程,所有的维护都来自于程序本身.它是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了.它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tc

  • Python轻量级ORM框架Peewee访问sqlite数据库的方法详解

    本文实例讲述了Python轻量级ORM框架Peewee访问sqlite数据库的方法.分享给大家供大家参考,具体如下: ORM框架就是 object relation model,对象关系模型,用来实现把数据库中的表 映射到 面向对象编程语言中的类,不需要写sql,通过操作对象就能实现 增删改查. ORM的基本技术有3种: (1)映射技术 数据类型映射:就是把数据库中的数据类型,映射到编程语言中的数据类型.比如,把数据库的int类型映射到Python中的integer 类型. 类映射:把数据库中的

  • Python操作SQLite数据库的方法详解【导入,创建,游标,增删改查等】

    本文实例讲述了Python操作SQLite数据库的方法.分享给大家供大家参考,具体如下: SQLite简介 SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中.它是D.RichardHipp建立的公有领域项目.它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了.它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl.C

  • C#操作SQLite数据库帮助类详解

    本文实例讲述了C#操作SQLite数据库帮助类.分享给大家供大家参考,具体如下: 最近有WPF做客户端,需要离线操作存储数据,在项目中考虑使用Sqlite嵌入式数据库,在网上找了不少资料,最终整理出一个公共的帮助类. Sqlite是一个非常小巧的数据库,基本上具备关系型数据库操作的大多数功能,Sql语法也大同小异.下面是我整理的帮助类代码: 1.获取 SQLiteConnection 对象,传入数据库有地址即可. /// <summary> /// 获得连接对象 /// </summar

随机推荐