`
zhangziyueup
  • 浏览: 1160669 次
文章分类
社区版块
存档分类
最新评论

Sqlite3 数据库介绍及常用方法的简单封装

 
阅读更多

SQLite是一个很小的C语言链接库。这个链接库本身就完全包含数据库引擎的功能,而且可以嵌入至其它程序中,完全不用额外的设定。其特性如下:


* 支持ACID (Atomic, Consistent, Isolated, Durable) 交易。
* 零组态设定(Zero-configuration),无须管理者的设定及管理。
* 支持大部分SQL92的语法。
* 数据库存在于一个单一的文件中。
* 数据库系统所在机器的字节顺序(Byte order)无关。
* 支援大小至2 TB (2^41 bytes)。
* 极小的内存需求:小于3万行的C语言程序代码。小于250KB的程序空间。
* 大部分的数据库操作皆快于一般流行的数据库系统。
* 简单易用的API。
* 支援TCL。也有其它语言的支持可用。
* 注释详细的程序代码,以及超过90%的测试。
* 链接库自己包含完整的功能,无须其它额外的程序或链接库。
* 程序代码版权为public domain。任何用途皆可免费使用。
* sqlite3 官方网站 www.sqlite3.org

SQLite的SQL从很大程度上实现了ANSI SQL92标准. 特别的SQLite支持视图, 触发器, 事务, 支持嵌套SQL. 这些都会在下面应用的过程中讲到, 故这边先暂时放下, 而主要说说SQLite所不支持的一些SQL.


1.不支持Exists, 虽然支持in(in是Exists的一种情况)
2.不支持多数据库, 如: create table db1.table1 as select * from db2.table1;
3.不支持存储过程
4.不支持Alter View/Trigger/Table
5.不支持Truncate, 在SQLite中Delete不带Where字句时和Truncate的效果是一样的.
6.不支持Floor和Ceiling函数, 还有其他蛮多的函数
7.没有Auto Increment(自增)字段, 但是SQLite其实是支持Auto Increment的, 即在将该字段设置为” INTEGER PRIMARY KEY”的时候.
8.不支持If Exists


详细的SQL支持可以访问: http://www.sqlite.org/lang.htm
详细的不支持SQL可以访问: http://www.sqlite.org/cvstrac/wiki?p=UnsupportedSql

SQLite的数据类型,首先你会接触到一个让你惊讶的名词: Typelessness(无类型). 对! SQLite是无类型的. 这意味着你可以保存任何类型的数据到你所想要保存的任何表的任何列中, 无论这列声明的数据类型是什么(只有在一种情况下不是, 稍后解释). 对于SQLite来说对字段不指定类型是完全有效的. 如: Create Table ex1(a, b, c);
诚然SQLite允许忽略数据类型, 但是仍然建议在你的Create Table语句中指定数据类型. 因为数据类型对于你和其他的程序员交流, 或者你准备换掉你的数据库引擎. SQLite支持常见的数据类型, 如:
CREATE TABLE ex2(
a VARCHAR(10),
b NVARCHAR(15),
c TEXT,
d INTEGER,
e FLOAT,
f BOOLEAN,
g CLOB,
h BLOB,
i TIMESTAMP,
j NUMERIC(10,5)
k VARYING CHARACTER (24),
l NATIONAL VARYING CHARACTER(16)
);
前面提到在某种情况下, SQLite的字段并不是无类型的. 即在字段类型为”Integer Primary Key”时.
SQLite的Wrapper 由于SQLite有别于其他数据库引擎的TCP/IP或RPC访问方式, 完全地是本地的操作, 从某种角度来说你可以说SQLite和MS的Access很相似, 但是更小更强大. 所谓Wrapper即使对SQLite提供的接口进行封装, 使其他语言可以访问, 使用SQLite. SQLite本身是提供C和Tcl的接口的. 所以可以非常轻易的和PHP相结合. 除了PHP的Wrapper以外, 还有许多世界各地的程序员提供了各种语言的SQLite的接口封装, 如Python, C++, Java, .Net…… 所流行的语言基本都有.

以下是代码:

#include <stdio.h>
#include <string.h>
#include "sqlite3.h"/* sqlite 数据库操作第三方库头文件 */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/

#ifdef WIN32
#pragma comment(lib, "sqlite3.lib")
#endif

#ifndef boolean
#define boolean
/* 定义布尔型变量 */
typedef enum boolean {false, true} bool;
#endif

#ifndef BOOLEAN
#define BOOLEAN
/* 定义布尔型变量 */
typedef enum BOOLEAN {FALSE, TRUE} BOOL;
#endif

/* 定义消息变量 */
typedef enum SQLT_MSG {SQLT_ERROR = -1, SQLT_DONE, SQLT_ROW} sqlt_msg;

/* 定义NULL字符 */
#define SQLT_NOTHING("(null)")

/* 定义NULL字符 */
#ifndef NULL
#define NULL0
#endif

/*---------------------------------------------------------------------------*/
/* 函数功能:格式化sqlite3数据库操作错误
* 参数说明:pSqlite3 发生错误的数据库指针
* 返回说明:返回NULL表示失败。
* 注意事项:
* 使用举例:1.if (open_sqlite(pSqlite3) == NULL)
* printf("sqlite close err(%s)", format_sqlite_err());
* */
char * format_sqlite_err(sqlite3 * pSqlite3)
{
if (pSqlite3 == NULL) return (char *)NULL;
return (char *)sqlite3_errmsg(pSqlite3);
}
/*---------------------------------------------------------------------------*/
/* 函数功能:打开数据库
* 参数说明:pszPath 待打开的数据库文件路径
* 返回说明:返回NULL表示失败。此时可使用format_err_sqlite函数得到错误文本信息
* 注意事项:如果没有对应的库文件,则产生一个新的数据库
* 使用举例:1.if (open_sqlite("test_sqlite.db") == NULL)
* printf("sqlite open err(%s)", format_sqlite_err());
* */
sqlite3 * open_sqlite(const char * pszPath)
{
static sqlite3 * pSqlite3;
pSqlite3 = NULL;

if (pszPath == NULL || strlen(pszPath) <= 7) return NULL;
if (sqlite3_open(pszPath, &pSqlite3) != SQLITE_OK) {

/* 如果 UTF-8 格式的数据库名打开失败,则再传入UTF-16 格式的数据库名 */
if (sqlite3_open16(pszPath, &pSqlite3) != SQLITE_OK) return NULL;
else return pSqlite3;
}
return pSqlite3;
}
/*---------------------------------------------------------------------------*/
/* 函数功能:关闭数据库
* 参数说明:pSqlite3 待关闭的数据库指针
* 返回说明:返回false表示失败。此时可使用format_err_sqlite函数得到错误文本信息
* 注意事项:
* 使用举例:1.if (close_sqlite(pSqlite3) == false)
* printf("sqlite close err(%s)", format_sqlite_err());
* */
bool close_sqlite(sqlite3 * pSqlite3)
{
if (pSqlite3 == NULL) return false;
if (sqlite3_close(pSqlite3) != SQLITE_OK) return false;
pSqlite3 = NULL;
return true;
}
/*---------------------------------------------------------------------------*/
/* 函数功能:获取第一行指定列数据库内容
* 参数说明:pSqlite3 待关闭的数据库指针(IN)
* pSqlite3_Stmtsqlite3_stmt 指针(OUT)
* pszSQL标准SQL语句
* nColunmID字段序号。从0开始
* 返回说明:返回NULL表示失败或数据库中没有纪录。
* 此时可使用format_err_sqlite函数得到错误文本信息
* 否则返回指定的字符串
* 注意事项:返回值应该判断是否为NULL
* 使用举例:1.遍历获取t_db表中t_db_ab字段的所有纪录并打印
* sqlite3 * pSqlite3;
* sqlite3_stmt * pSqlite3_Stmt;
* char *pszTxt = NULL;
* for (pszTxt = first_sqlite_column_txt(pSqlite3, &pSqlite3_Stmt, "select t_bd_ab from t_bd", 0);
* pszTxt != NULL;
* pszTxt = next_sqlite_column_txt(pSqlite3_Stmt, 0))
* {
* printf("%s\r\n", pszTxt == NULL ? NOTHING : pszTxt);
* sqlite_ret = step_sqlite_row(pSqlite3_Stmt);
* if (sqlite_ret == SQLT_ERROR) {
*
* printf("step_sqlite_row err(%s)\r\n", format_sqlite_err(pSqlite3));
* break;
* }
* else if (sqlite_ret == SQLITE_DONE) break;
* }
* */
#ifdef MACRO_C
char * first_sqlite_column_txt(sqlite3 * pSqlite3, sqlite3_stmt ** pSqlite3_Stmt, const char * pszSQL, const unsigned int nColunmID)
#else
char * first_sqlite_column_txt(sqlite3 * pSqlite3, sqlite3_stmt ** pSqlite3_Stmt, const char * pszSQL, const unsigned int &nColunmID = 0)
#endif
{
/* 检查参数 */
if (pSqlite3 == NULL || nColunmID < 0) {

*pSqlite3_Stmt = NULL;
return (char *)NULL;
}
if (sqlite3_prepare(pSqlite3, pszSQL, -1, pSqlite3_Stmt, 0) != SQLITE_OK) {

if (sqlite3_prepare16(pSqlite3, pszSQL, -1, pSqlite3_Stmt, 0) != SQLITE_OK) {

*pSqlite3_Stmt = NULL;
return (char *)NULL;
}
}
if (sqlite3_step(*pSqlite3_Stmt) != SQLITE_ROW) {

if (*pSqlite3_Stmt != NULL) {

sqlite3_finalize(*pSqlite3_Stmt);
*pSqlite3_Stmt = NULL;
}
return (char *)NULL;
}
return (char *)sqlite3_column_text(*pSqlite3_Stmt, nColunmID);
}

/* 函数功能:获取数据库当前行指定列的数据
* 参数说明:pSqlite3_Stmtsqlite3_stmt 指针(IN/OUT)
* nColunmID对应数据表中字段的ID号,从0开始
* 返回说明:返回NULL表示失败。此时可使用format_sqlite_err函数得到错误文本信息
* 否则返回指定的字符串
* 注意事项:返回值应该判断是否为NULL
* 使用举例:参见:first_sqlite_column_txt 函数
* */
#ifdef MACRO_C
char * next_sqlite_column_txt(sqlite3_stmt * pSqlite3_Stmt, const unsigned int nColunmID)
#else
char * next_sqlite_column_txt(sqlite3_stmt * pSqlite3_Stmt, const unsigned int &nColunmID = 0)
#endif
{
if (pSqlite3_Stmt == NULL || nColunmID < 0) return (char *)NULL;
return (char *)sqlite3_column_text(pSqlite3_Stmt, nColunmID);
}

/* 函数功能:将数据库游标移动到下一行
* 参数说明:pSqlite3_Stmtsqlite3_stmt 指针(IN/OUT)
* 返回说明:返回 SQLT_ERROR表示失败。此时可使用format_sqlite_err函数得到错误文本信息
* 返回 SQLT_DONE表示当前游标及以下没有纪录了。
* 返回 SQLT_ROW表示游标移动下一行
* 注意事项:1.遍历获取数据库内容时,当返回 SQLT_ERROR 和 SQLITE_DONE
* 时,则该退出循环
* 使用举例:参见:first_sqlite_column_txt 函数
* */
sqlt_msg step_sqlite_row(sqlite3_stmt * pSqlite3_Stmt)
{
int sqlite_ret = 0;

if (pSqlite3_Stmt == NULL) return SQLT_ERROR;

sqlite_ret = sqlite3_step(pSqlite3_Stmt);
if (sqlite_ret == SQLITE_ROW) return SQLT_ROW;
else if (sqlite_ret == SQLITE_DONE) {

sqlite3_finalize(pSqlite3_Stmt);
pSqlite3_Stmt = NULL;
return SQLT_DONE;
}
return SQLT_ERROR;
}
/*---------------------------------------------------------------------------*/
/* 函数功能:开启事务
* 参数说明:pSqlite3sqlite3 指针
* 返回说明:返回 false表示失败。此时可使用format_sqlite_err函数得到错误文本信息
* 注意事项:1.必须和'关闭事务'成对使用
* 使用举例:
* */
bool begin_sqlite_affair(sqlite3 * pSqlite3)
{
if (pSqlite3 == NULL) return false;
if (sqlite3_exec(pSqlite3, "BEGIN;", 0, 0, 0) != SQLITE_OK) return false;
return true;
}
/* 函数功能:关闭事务
* 参数说明:pSqlite3sqlite3 指针
* 返回说明:返回 false表示失败。此时可使用format_sqlite_err函数得到错误文本信息
* 注意事项:1.必须和'开启事务'成对使用
* 使用举例:
* */
bool end_sqlite_affair(sqlite3 * pSqlite3)
{
if (pSqlite3 == NULL) return FALSE;
if (sqlite3_exec(pSqlite3, "COMMIT;", 0, 0, 0) != SQLITE_OK) return false;
return true;
}
/*---------------------------------------------------------------------------*/
/* 函数功能:执行 SQL 语句
* 参数说明:pSqlite3sqlite3 指针
* pszSQL需要执行的 SQL 字符串语句
* 返回说明:返回 false表示失败。此时可使用format_sqlite_err函数得到错误文本信息
* 注意事项:
* 使用举例:
* */
bool execute_sql(sqlite3 * pSqlite3, const char * pszSQL)
{
if (pSqlite3 == NULL) return false;
if (sqlite3_exec(pSqlite3, pszSQL, 0, 0, 0) != SQLITE_OK) return false;
return true;
}
/*---------------------------------------------------------------------------*/
/* 函数功能:获取执行 SQL 语句后所查询的数据字段数量
* 参数说明:pSqlite3sqlite3 指针
* pSqlite3_Stmtsqlite3_stmt 指针
* pszSQL需要执行的 SQL 字符串语句
* 返回说明:返回 -1表示失败。此时可使用format_sqlite_err函数得到错误文本信息
* 否则返回字段数量
* 注意事项:
* 使用举例:1.得到t_bd表中字段总合数量
* int sqlite_colunm_count = 0;
* sqlite_colunm_count = get_colunm_count(pSqlite3, &pSqlite3_Stmt, "select * from t_bd");
* if (sqlite_colunm_count < 0) {
*
* printf("get_colunm_count err(%s)\r\n", format_sqlite_err(pSqlite3));
* }
* else printf("sqlite colunm count = %d\r\n", sqlite_colunm_count);
* */
int get_colunm_count(sqlite3 * pSqlite3, sqlite3_stmt ** pSqlite3_Stmt, const char * pszSQL)
{
static int nsqlite_colunm;

nsqlite_colunm = 0;
/* 检查参数 */
if (pSqlite3 == NULL) {

pSqlite3_Stmt = NULL;
return -1;
}
if (sqlite3_prepare(pSqlite3, pszSQL, -1, pSqlite3_Stmt, 0) != SQLITE_OK) {

if (sqlite3_prepare16(pSqlite3, pszSQL, -1, pSqlite3_Stmt, 0) != SQLITE_OK) {

pSqlite3_Stmt = NULL;
return -1;
}
}
if (sqlite3_step(*pSqlite3_Stmt) != SQLITE_ROW) {

if (pSqlite3_Stmt != NULL) {

sqlite3_finalize(*pSqlite3_Stmt);
pSqlite3_Stmt = NULL;
}
return -1;
}
nsqlite_colunm = sqlite3_column_count(*pSqlite3_Stmt);
if (*pSqlite3_Stmt != NULL) {

sqlite3_finalize(*pSqlite3_Stmt);
pSqlite3_Stmt = NULL;
}

return nsqlite_colunm;
}
/*---------------------------------------------------------------------------*/
/* 函数功能:压缩 sqlite 数据
* 参数说明:pSqlite3sqlite3 指针
* 返回说明:返回 false表示失败。此时可使用format_sqlite_err函数得到错误文本信息
* 注意事项:需要使用两倍于数据库文件大小的磁盘空间
* 使用举例:
* */
bool sqlite_compress(sqlite3 * pSqlite3)
{
if (pSqlite3 == NULL) return false;
if (sqlite3_exec(pSqlite3, "VACUUM;", 0, 0, 0) != SQLITE_OK) return false;
return true;
}
/*---------------------------------------------------------------------------*/
/* 函数功能:获取一列的列名称
* 参数说明:pSqlite3sqlite3 指针
* pSqlite3_Stmtsqlite3_stmt 指针
* pszSQL需要执行的 SQL 字符串语句
* nColunmID执行 SQL 后,对结果中的字段ID
* 返回说明:返回 NULL 表示失败。此时可使用format_sqlite_err函数得到错误文本信息
* 注意事项:
* 使用举例:
* */
#ifdef MACRO_C
char * sqlite_colunm_name(sqlite3 * pSqlite3, sqlite3_stmt ** pSqlite3_Stmt, const char * pszSQL, const unsigned int nColunmID)
#else
char * sqlite_colunm_name(sqlite3 * pSqlite3, sqlite3_stmt ** pSqlite3_Stmt, const char * pszSQL, const unsigned int &nColunmID = 0)
#endif
{
static char szColunm[128];
char * pszColunm_Name;

/* 检查参数 */
if (pSqlite3 == NULL) {

pSqlite3_Stmt = NULL;
return (char *)NULL;
}
memset(szColunm, 0, 128);
if (sqlite3_prepare(pSqlite3, pszSQL, -1, pSqlite3_Stmt, 0) != SQLITE_OK) {

if (sqlite3_prepare16(pSqlite3, pszSQL, -1, pSqlite3_Stmt, 0) != SQLITE_OK) {

pSqlite3_Stmt = NULL;
return (char *)NULL;
}
}
if (sqlite3_step(*pSqlite3_Stmt) != SQLITE_ROW) {

if (pSqlite3_Stmt != NULL) {

sqlite3_finalize(*pSqlite3_Stmt);
pSqlite3_Stmt = NULL;
}
return (char *)NULL;
}
pszColunm_Name = (char *)sqlite3_column_name(*pSqlite3_Stmt, nColunmID);
sprintf(szColunm, "%s", pszColunm_Name == NULL ? "" : pszColunm_Name);
if (*pSqlite3_Stmt != NULL) {

sqlite3_finalize(*pSqlite3_Stmt);
pSqlite3_Stmt = NULL;
}
return szColunm;
}

本文转自:http://apps.hi.baidu.com/share/detail/15012229
分享到:
评论

相关推荐

    sqlite3数据库操作类

    此类集成了许多数据库常用操作和一些不常用操作的方法和实例(包括blob数据类型的操作,此blob类型的读写不限于单个读写,可自由灵活的操作多个blob字段);本程序为本人对sqlite3的包装,目的在于更方便的调用数据库...

    sqlite3封装类

    封装该类的目的:统一sqlite数据库接口,以方便windows/linux平台间使用sqlite数据库。 该类封装了sqlite3常用操作(可执行 增删改查,事务,创建/增加sql函数,数据库文件压缩等) 该类的使用方法见sqldb.h,该头文件...

    c#几种常用数据库封装

    常用的几种数据库封装,介绍已经在博文中写了。sqlite,berkeleydb,一般关系数据库。其中还包括序列化,通信,你可以自由组合。

    android sqlite数据库封装 实现crud

    数据库的方式,常用在存储一系列的结构复杂的数据,轻量级的数据库SQlit使用起来还是比较简单,但是总想能像hibernate似的框架可以进行下封装,实现orm并且可以实现简单的rcud。项目中只有封装包,使用过程很简单,...

    C#官方通用类库及通用数据库类库

    1. 通用类库 DC.CommonLiteLib针对一些常用算法,线程管理,IO控制,以及ConvertHelper类型转换,StringHelper字符串封装,FileHelper 文件操作封装等,另有CHM官方文件解释用法。 2. 用数据库类库 DC....

    python 自用sqlite库

    python sqlite 工具 通用库,常用的 数据库操作增删改查,增加表,库等

    android SQLite数据库总结

    SQLite是一种超轻量级的嵌入式数据库,大小只有几百KB,但是其语法支持标准SQL语法,同时还遵循了数据库的ACID事务,所以学过其他数据库的开发人员都很容易掌握其使用。 sql语法就不介绍了,直接看在android中的使用...

    放弃Database库函数(access)的使用, 使用轻小型数据库sqlite,打包套件

    Sqlite数据库采用.db文件存储,使用Navicate软件打开结果如下,该软件回提示写SQ语句相关实例,并提示SQ语句的语法错误,常用的查找,删除,更新等数据库操作,该软件相比于access数据库具有很大的编成优势,在软件...

    sql_engine-1.0.0.tar.gz_CppSQLite3_2_mysql封装库_oracle_sqlite wrap

    支持常用数据库的数据库封装类,支持mysql,sqlite,oracle,等

    SQLite的操作流程

    该项目,对于SQLite常用的操作进行的详细的说明并进行了封装,集成进入项目中非常方便

    SqliteHelper.zip

    采用ReaderWriterLockSlim锁,实现读写锁分离,多线程操作sqlite...参考 让C#轻松实现读写锁分离--封装ReaderWriterLockSlim C#解决SQlite并发异常问题的方法(使用读写锁)2篇文章,已经封装sqlite常用增删改查函数。

    c++ sqlite帮助类

    自己编写的一个c++ 版sqlite数据库访问帮助类,主要对sqlite的常用的几个接口函数进行封装成一个类,实现查询、事务处理等基本数据库访问应用,简单,好用,希望对大家有用,注意传人的参数是stl 的string 类型,...

    Sqlite 常用函数封装提高Codeeer的效率

    内容格式相对固定,封装一下有助于提高开发效率(^_^至少提高Codeeer的效率了) 而且,我发现Sqlite中文资料比较少,起码相对其他找起来要复杂些,服务一下大众~ 我没有封装读取部分,因为数据库读取灵活性太大,...

    Flutter持久化存储之数据库存储(sqflite)详解

    数据库存储是我们常用的存储方式之一,对大批量数据有增、删、改、查操作需求时,我们就会想到使用数据库,Flutter中提供了一个sqflite插件供我们用于大量数据执行CRUD操作。本篇我们就来一起学习sqflite的使用。 ...

    SQLlite数据库帮助类

    sqlite数据库常用工具类:ExecuteDataSet、UpdateDataset等对比表的增删改查封装

    C#(VB.net)数据库访问操作类库

    你知道,一些类库把常用的操作封装起来,以后可以直接调用,就节省了普通开发人员的大量精力. 对于CN 大多数公司都是开发MIS系统 说白了就是数据库系统 使用数据访问类库,必将节省大量代码 网上有个通用数据访问类库 ...

    C#访问数据库封装包,可实现增删改查所有功能的快捷操作,支持所有常用数据库。

    SqlServer, MySql, SQLite, Oracle, ODBC, OleDb, Firebird, PostgreSql, DB2, Informix, SqlServerCe

    C#封装的Sqlite访问类实例

    主要介绍了C#封装的Sqlite访问类,实例分析了C#针对Sqlite数据库各种常用操作的相关技巧,需要的朋友可以参考下

    使用LitePal操作SQLite数据库(增删查改)

    LitePal是一款开源的Android数据库框架,它采用了对象关系映射(ORM)模式,并将我们平时开发常用的一些数据库功能进行封装,使得不用编写一行SQL语句就可以 完成各种建表和增删查改操作。我们使用的编译语言是面向...

    详解Android中一些SQLite的增删改查操作

    在Android开发中经常要涉及到对数据的操作。Android本身提供了四种数据存储方式。包括:SharePreference,SQLite,Content ...SharedPreference: 除SQLite数据库外,另一种常用的数据存储方式,其本质就是一个xml

Global site tag (gtag.js) - Google Analytics