博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
第六章 核心API
阅读量:5988 次
发布时间:2019-06-20

本文共 13747 字,大约阅读时间需要 45 分钟。

一、查询封装

1、连接与断开连接

  打开数据库API如下:

1 int sqlite3_open( 2   const char *zFilename,    /* Database filename (UTF-8) */ 3   sqlite3 **ppDb         /* OUT: SQLite db handle */ 4 ) 5  6 int sqlite3_open_v2( 7   const char *filename,   /* Database filename (UTF-8) */ 8   sqlite3 **ppDb,            /* OUT: SQLite db handle */ 9   int flags,                      /* Flags */10   const char *zVfs          /* Name of VFS module to use */11 )12 13 int sqlite3_open16(14   const void *zFilename,     /* Database filename (UTF-16) */15   sqlite3 **ppDb        /* OUT: SQLite db handle */16 )

   1)zFilename

  • 使用”:memory",sqlite3_open_v2()将在内存中创建数据库,只存在于连接生存期间。
  • null:sqlite3_open_v2()将打开临时磁盘文件,并在连接关闭时自动删除该文件。
  • 其他:sqlite3_open_v2()将通过该名字打开一个新的数据库文件,如果不包含SQLITE_OPEN_CREATE,将返回错误。

   2)flags

  以下均为比特向量:

  • SQLITE_OPEN_CREATE
  • SQLITE_OPEN_READONLY
  • SQLITE_OPEN_READWRITE

  可结合以下标志使用

  • SQLITE_OPEN_NOMUTEX: 设置数据库连接运行在多线程模式(没有指定单线程模式的情况下)
  • SQLITE_OPEN_FULLMUTE:设置数据库连接运行在串行模式。
  • SQLITE_OPEN_SHAREDCACHE:设置运行在共享缓存模式。
  • SQLITE_OPEN_PRIVATECACHE:设置运行在非共享缓存模式。

 

  3)ppDb

  可视为一个不透明句柄,代表到数据库的一个连接。可能将多个数据库附加到单个连接上。无论多少个数据库附加到带连接上,它依然代表事务上下文环境。

  4)zVfs

  允许调用去重写默认的操作系统接口sqlite3_vfs方法。

 

  关闭数据库API如下:

1 int sqlite3_close(sqlite3 *db)2 int sqlite3_close_v2(sqlite3 *db)

 

调用sqlite3_close()时,如果有查询仍未完成,会返回SQLITE_BUSY,并显示错误消息“由于有位完成的语句,所以无法关闭连接” 调用sqlite3_close_v2()时,若关闭时连接有未提交的事务,该事务会自动回滚。

 

2、执行查询

  sqlite3_exec()提供了一种快速、方便执行SQL命令的方法。

int sqlite3_exec(  sqlite3 *db,                /* The database on which the SQL executes */  const char *zSql,           /* The SQL to be executed */  sqlite3_callback xCallback, /* Invoke this callback routine */  void *pArg,                 /* First argument to xCallback() */  char **pzErrMsg             /* Write error messages here */)

 

   1)zsql

  可包含多个SQL命令。插入一条记录时,如果数据库尚未存在,创建表命令从物理上创建数据库文件。

   2)xCallback、 pArg

  通过上述两个参数实现回调函数。

  xCallback:提供指向回调函数的指针

  pArg:void指针,执行要提供给回调函数的应用程序特定的数据,回调函数的第一个参数。

  下面是回调函数的类型声明:

1 typedef int (*sqlite3_callback)(void*,int,char**, char**);

   参数:

  • 第一个参数:sqlite3_exec()函数的第四个参数提供的数据
  • 第二个参数:行中字段的数目
  • 第三个参数:代表行中字段名称的字符串数据
  • 第四个参数:代表字段名称的字符串数组

  3)pzErrMsg

  指向错误消息字符串的执政,可将处理中发生的错误消息写入该字符串。

  errmsg指向的错误信息在堆上分配的,故如果errmsg不为NULL,则需要调用sqlite3_free()释放errmsg所占用的内存。

  注意:如果回调函数的返回值不为0,将会影响sqlite3_exec()的执行。将会终止当前命令和sql字符串后续命令的所有处理。

 

3、获取表查询

  sqlite3_get_table()封装了sqlite3_exec()。不必处理回调函数,更容易获取记录。但最新的文档,不建议用此接口。

1 int sqlite3_get_table(2   sqlite3 *db,                /* The database on which the SQL executes */3   const char *zSql,           /* The SQL to be executed */4   char ***pazResult,          /* Write the result table here */5   int *pnRow,                 /* Write the number of rows in the result here */6   int *pnColumn,              /* Write the number of columns of result here */7   char **pzErrMsg             /* Write error messages here */8 )

 1)pazResult

  查询结果存储位置指针。必须调用sqlite3_free_table()释放内存。pazResult中第一个记录是列的名称,即先打印出查询内容的各个字段名称。

  打印结果的每一行和每一列:

1 rc = sqlite3_get_table(db, sql, &result, &nrows, &ncols, &zErr);2 3 for(i=0; i < nrows; i++) {4     for(j=0; j < ncols; j++) {5         /* the i+1 term skips over the first record,6         which is the column headers */7         fprintf(stdout, "%s", result[(i+1)*ncols + j]);8     }9 }

 

二、查询准备

   列值可通过sqlite3_column_xxx()获得。其中xxx表示返回值的声明类型(如int、double、blob)。

  查询准备有三个步骤:编译、执行和完成。

  使用sqlite3_prepare_v2()编译查询,使用函数sqlite3_step()分步执行查询,使用函数sqlite_finalize()关闭查询,或使用sqlit3_reset()重用编译。

1、编译

  编译或准备接收SQL语句,并将其编译为虚拟数据库殷勤(VDBE)可读字节码。

  sqlite3_prepare_v2()可直接通过编译器工作,为执行准备查询。语句句柄高度依赖它所被编译的数据库模式。如果另一个连接在准备语句和实际执行语句期间更改了数据库模式,那么准备语句就会失效。有可能的话,函数会自动试图重新编译(重准备)语句。如果重新编译无法实现,sqlite3_step()调用会导致SQLITE_SCHEMA错误

1 int sqlite3_prepare_v2(2   sqlite3 *db,              /* Database handle. */3   const char *zSql,         /* UTF-8 encoded SQL statement. */4   int nBytes,               /* Length of zSql in bytes. */5   sqlite3_stmt **ppStmt,    /* OUT: A pointer to the prepared statement */6   const char **pzTail       /* OUT: End of parsed string */7 )

  1)ppStmt

  sqlite3_stmt类型结构体。这种数据结构包含了命令的字节码、绑定的参数、B-tree游标、执行上下文以及sqlite3_step()在执行过程中管理查询状态所需的其他数据。

  能够使用sqlite3_setp()执行编译好的准备语句的指针,如果发生错误,它被置位NULL,如输入的文本不包括sql语句。调用过程必须负责在编译好的sql语句完成使用后使用sqlit3_finalize()删除它。

  2)pzTail

  zSql在遇见终止符或者是达到设定的nByte之后结束,假如zSql还有剩余的内容,那么这些剩余的内容被存放到pZTail中,不包括终止符。如果pszTail不为NULL, 则*pszTail指向sql中第一个被传入的SQL语句的结尾。该函数只编译sql的第一个语句, 所以*pszTail指向的内容则是未被编译的。

  说明:

  如果函数执行成功,则返回SQLITE_OK,否者返回一个错误码。

  备注:

  <1>准备语句(prepareed statement)对象

1 typedef struct sqlite3_stmt sqlite3_stmt;

   一个准备语句(prepared statement)对象代表一个简单SQL语句对象的实例,这个对象通常被称为“准备语句”或者“编译好的SQL语句”或者就直接称为“语句”。

  语句对象的生命周期经历这样的过程:

  • 使用sqlite3_prepare_v2或相关的函数创建这个对象
  • 使用sqlite3_bind_*()给宿主参数(host parameters)绑定值
  • 通过调用sqlite3_step一次或多次来执行这个sql
  • 使用sqlite3——reset()重置这个语句,然后回到第2步,这个过程做0次或多次
  • 使用sqlite3_finalize()销毁这个对象

  在sqlite中并没有定义sqlite3_stmt这个结构的具体内容,它只是一个抽象类型,在使用过程中一般以它的指针进行操作,而sqlite3_stmt类型的指针在实际上是一个指向Vdbe(虚拟机实例)的结构体得指针。

  <2>宿主参数(host parameters)

  在传给sqlite3_prepare_v2()的sql的语句文本或者它的变量中,满足如下模板的文字将被替换成一个参数:

  | ?

  | ?NNN  //NNN代表数字  
  | :VVV  //VVV代表字符
  | @VVV
  | $VVV
  在上面这些模板中,NNN代表一个数字,VVV代表一个字母数字标记符(例如:222表示名称为222的标记符),sql语句中的参数(变量)通过上面的几个模板来指定,如“select ? from ? “这个语句中指定了两个参数,sqlite语句中的第一个参数的索引值是1,这就知道这个语句中的两个参数的索引分别为1和2,使用”?”的话会被自动给予索引值,而使用”?NNN”则可以自己指定参数的索引值,它表示这个参数的索引值为NNN。”:VVV”表示一个名为”VVV”的参数,它也有一个索引值,被自动指定。

  例如:

INSERT INTO people (id, name) VALUES ( ?, ? );INSERT INTO people (id, id2,name) VALUES ( ?1, ?1.?2 );  //作用:可以用同一个值绑定几个变量INSERT INTO people (id, name) VALUES ( :id, :name );INSERT INTO people (id, name) VALUES ( @id, @name );INSERT INTO people (id, name) VALUES ( $id, $name );  //用来支持Tcl变量的扩展语法,除非使用Tcl编程,否则推荐使用“:
”版本

  可以使用sqlite3_bind_*()来给这些参数绑定值。

 

2、执行

int sqlite3_step(sqlite3_stmt *pStmt)

 

   sqlite3_step()接收句柄并直接与VDBE通信,生成执行SQL语句的字节码指令。第一次调用时,VDBE获得执行该命令所需的必要的数据库锁。如果不能获取锁,并没有指派繁忙处理程序,sqlite3_step()将返回SQLITE_BUSY。如果指定了繁忙处理程序,将调用该处理程序。

  对于返回数据的SQL语句,sqlite3_step()第一次调用将语句定位在第一个记录的B-tree光标上。后续调用将定位在结果集内的后续记录。到达末尾值前,sqlite3_step()为结果集中的每个记录返回SQLITE_ROW,返回SQLITE_DONE,表示已到达结果集末尾。

3、完成与重置

1 int sqlite3_finalize(sqlite3_stmt *pStmt);2 int sqlite3_reset(sqlite3_stmt *pStmt);

 

  •  sqlite3_finalize()将关闭语句。释放资源并提交或回滚任何隐式事务(如果该链接是自动自动提交模式),清除日志文件并释放相关联的锁。
  •  sqlite3_reset()将保持已编译的SQL语句(和任何绑定的参数),但会将语句相关联的变化提交到数据库。如果启动了自动提交,它还释放锁定并清除日志文件。此函数保留与语句关联的资源。避免了再次调用sqlite3_prepare()。

 示例(未处理错误、繁忙条件等):

1 #include 
2 #include
3 4 int main(int argc, char **argv) 5 { 6 int rc, i, ncols; 7 sqlite3 *db; 8 sqlite3_stmt *stmt; 9 char *sql;10 const char *tail;11 12 rc = sqlite3_open("foods.db", &db);13 14 if(rc) {15 fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));16 sqlite3_close(db);17 exit(1);18 }19 20 sql = "select * from episodes;";21 22 rc = sqlite3_prepare_v2(db, sql, strlen(sql), &stmt, &tail);23 24 if(rc != SQLITE_OK) {25 fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));26 }27 28 rc = sqlite3_step(stmt);29 ncols = sqlite3_column_count(stmt);30 31 while(rc == SQLITE_ROW) {32 33 for(i=0; i < ncols; i++) {34 fprintf(stderr, "'%s' ", sqlite3_column_text(stmt, i));35 }36 37 fprintf(stderr, "\n");38 39 rc = sqlite3_step(stmt);40 }41 42 sqlite3_finalize(stmt);43 sqlite3_close(db);44 45 return 0;46 }

 

 

  sqlite3_prepare_v2()支持多条SQL语句的处理方法。

1 while(sqlite3_complete(sql))2 {3     rc = sqlite3_prepare(db,sql, -1, &stmt, &tail);4 5     /*处理查询结果*/    6 7     /*跳到字符串的下一条命令*/8     sql = tail;9 }

 

 

三、获取记录

1 /* 2 ** Return the number of columns in the result set for the statement pStmt. 3 */ 4 int sqlite3_column_count(sqlite3_stmt *pStmt) 5  6 /* 7 ** Return the number of values available from the current row of the 8 ** currently executing statement pStmt. 9 */10 int sqlite3_data_count(sqlite3_stmt *pStmt)
  • sqlite3_column_count():返回与语句句柄相关联的字段数,如果请求不是select语句,则sqlite3_column_count()返回0;
  • sqlite3_data_count():sqlite3_step()返回SQLITE_ROW后,返回会当前记录的列数。只有语句句柄存在活动游标是,该函数才能工作。

1、获取字段信息

1 /*2 ** Return the name of the Nth column of the result set returned by SQL3 ** statement pStmt.4 */5 const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N)

  获取当前记录中的所有列的名字。

 

1 int sqlite3_column_type(sqlite3_stmt *pStmt, /*语句句柄*/2                                int i /*字段的次序*/);3 4 #define SQLITE_INTEGER  15 #define SQLITE_FLOAT    26 #define SQLITE_BLOB     47 #define SQLITE_NULL     5

 

  获取每个字段相关联的存储类。

 

/*** Return the column declaration type (if applicable) of the 'i'th column** of the result set of SQL statement pStmt.*/const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N)

 

  获取字段在表模式定义中声明的数据类型。

  如果结果集中的列与实际表中的列不对应,该函数将返回NULL。

 

1 /* 2 ** Return the name of the database from which a result column derives. 3 ** NULL is returned if the result column is an expression or constant or 4 ** anything else which is not an unambiguous reference to a database column. 5 */ 6 const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int N) 7  8 /* 9 ** Return the name of the table from which a result column derives.10 ** NULL is returned if the result column is an expression or constant or11 ** anything else which is not an unambiguous reference to a database column.12 */13 const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int N)14 15 /*16 ** Return the name of the table column from which a result column derives.17 ** NULL is returned if the result column is an expression or constant or18 ** anything else which is not an unambiguous reference to a database column.19 */20 const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N)

 

  上面三个函数的功能:

  • 返回列相关联的数据库
  • 返回它所在的表
  • 返回列在模式中的定义名称

  上述函数只有在编译SQLite时启用了SQLITE_ENABLE_COLUMN_METADATA预处理指令时,才可用。

 

2、获取字段值

  通过以下API获取字段值。

1 /**************************** sqlite3_column_  ******************************* 2 ** The following routines are used to access elements of the current row 3 ** in the result set. 4 */ 5 const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){ 6   const void *val; 7   val = sqlite3_value_blob( columnMem(pStmt,i) ); 8   /* Even though there is no encoding conversion, value_blob() might 9   ** need to call malloc() to expand the result of a zeroblob() 10   ** expression. 11   */12   columnMallocFailure(pStmt);13   return val;14 }15 int sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){16   int val = sqlite3_value_bytes( columnMem(pStmt,i) );17   columnMallocFailure(pStmt);18   return val;19 }20 int sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){21   int val = sqlite3_value_bytes16( columnMem(pStmt,i) );22   columnMallocFailure(pStmt);23   return val;24 }25 double sqlite3_column_double(sqlite3_stmt *pStmt, int i){26   double val = sqlite3_value_double( columnMem(pStmt,i) );27   columnMallocFailure(pStmt);28   return val;29 }30 int sqlite3_column_int(sqlite3_stmt *pStmt, int i){31   int val = sqlite3_value_int( columnMem(pStmt,i) );32   columnMallocFailure(pStmt);33   return val;34 }35 sqlite_int64 sqlite3_column_int64(sqlite3_stmt *pStmt, int i){36   sqlite_int64 val = sqlite3_value_int64( columnMem(pStmt,i) );37   columnMallocFailure(pStmt);38   return val;39 }40 const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){41   const unsigned char *val = sqlite3_value_text( columnMem(pStmt,i) );42   columnMallocFailure(pStmt);43   return val;44 }45 sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){46   Mem *pOut = columnMem(pStmt, i);47   if( pOut->flags&MEM_Static ){48     pOut->flags &= ~MEM_Static;49     pOut->flags |= MEM_Ephem;50   }51   columnMallocFailure(pStmt);52   return (sqlite3_value *)pOut;53 }54 #ifndef SQLITE_OMIT_UTF1655 const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){56   const void *val = sqlite3_value_text16( columnMem(pStmt,i) );57   columnMallocFailure(pStmt);58   return val;59 }60 #endif /* SQLITE_OMIT_UTF16 */

 

 

   数据类型转换:

  对于BLOB列,通过sqlite3_column_bytes()获取实际数据的长度。示例如下:

1 int len = sqlite3_column_bytes(stmt, 0);2 void* data = malloc(len);3 memcpy(data, len, sqlite3_column_blob(stmt,0));

 

 

 实例代码:

1 #include 
2 #include
3 4 int main(int argc, char **argv) 5 { 6 int rc, i, ncols, id, cid; 7 char *name, *sql; 8 sqlite3 *db; 9 sqlite3_stmt *stmt;10 11 sql = "select id, name from episodes";12 sqlite3_open("test.db", &db);13 14 setup(db);15 16 sqlite3_prepare_v2(db, sql, strlen(sql), &stmt, NULL);17 18 ncols = sqlite3_column_count(stmt);19 rc = sqlite3_step(stmt);20 21 /* Print column information */22 for(i=0; i < ncols; i++) {23 fprintf(stdout, "Column: name=%s, storage class=%i, declared=%s\n",24 sqlite3_column_name(stmt, i),25 sqlite3_column_type(stmt, i),26 sqlite3_column_decltype(stmt, i));27 }28 fprintf(stdout, "\n");29 30 while(rc == SQLITE_ROW) {31 id = sqlite3_column_int(stmt, 0);32 cid = sqlite3_column_int(stmt, 1);33 name = sqlite3_column_text(stmt, 2);34 if(name != NULL){35 fprintf(stderr, "Row: id=%i, cid=%i, name='%s'\n", id,cid,name);36 } else {37 /* Field is NULL */38 fprintf(stderr, "Row: id=%i, cid=%i, name=NULL\n", id,cid);39 }40 rc = sqlite3_step(stmt);41 }42 43 sqlite3_finalize(stmt);44 sqlite3_close(db);45 return 0;46 }

 

 

  另,可通过一个给定的语句句柄,获取关联连接句柄。这个函数免除了到处传递关联连接句柄的麻烦。

1 /*2 ** Return the sqlite3* database handle to which the prepared statement given3 ** in the argument belongs.  This is the same database handle that was4 ** the first argument to the sqlite3_prepare() that was used to create5 ** the statement in the first place.6 */7 sqlite3 *sqlite3_db_handle(sqlite3_stmt *pStmt)

转载于:https://www.cnblogs.com/mofei004/p/9392010.html

你可能感兴趣的文章
Foxify v0.10.7 发布,基于 TypeScript 的 Node 框架
查看>>
【Linux】Bash Shell之命令续篇
查看>>
node.js 编程 小知识
查看>>
httpd关于php
查看>>
第62期CIO时代信息化大讲堂:智能运维与海量日志分析
查看>>
linux第九周微职位
查看>>
Office 365 系列之七:安装 Office 365 ProPlus
查看>>
mysql报错问题解决Character set 'utf8mb4' is not a compil
查看>>
菜鸟学Linux 第105篇笔记 海量存储解决
查看>>
nginx HTTP Upstream模块
查看>>
Debug记录:vCenter6.5突然不能访问并报错“503 Service Unavailable”
查看>>
Win8 Metro(C#)数字图像处理--2.58双峰法图像二值化
查看>>
swap脚本命令
查看>>
#24 centos6(RHEL)系列操作系统的启动流程、与命令chkconfig、grub的使用
查看>>
JS实现填报时对修改过的单元格进行标识
查看>>
SVN用户管理脚本(先放添加部分)
查看>>
CArchive串行化操作
查看>>
How to Join the vCSA 6.5 to an Active Directory Domain
查看>>
Ubuntu中如何安装LaTeX宏包
查看>>
Go语言之Doc 文档
查看>>