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

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
sql

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…… 所流行的语言基本都有.
app

如下是代码:less

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

#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;
spa

/* 定义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;}/*---------------------------------------------------------------------------*//*-------------------------------- END --------------------------------------*/