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 NULL 0
#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_Stmt sqlite3_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_Stmt sqlite3_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_Stmt sqlite3_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;
}
/*---------------------------------------------------------------------------*/
/* 函数功能: 开启事务
* 参数说明: pSqlite3 sqlite3 指针
* 返回说明: 返回 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;
}
/* 函数功能: 关闭事务
* 参数说明: pSqlite3 sqlite3 指针
* 返回说明: 返回 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 语句
* 参数说明: pSqlite3 sqlite3 指针
* 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 语句后所查询的数据字段数量
* 参数说明: pSqlite3 sqlite3 指针
* pSqlite3_Stmt sqlite3_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 数据
* 参数说明: pSqlite3 sqlite3 指针
* 返回说明: 返回 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;
}
/*---------------------------------------------------------------------------*/
/* 函数功能: 获取一列的列名称
* 参数说明: pSqlite3 sqlite3 指针
* pSqlite3_Stmt sqlite3_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;
}