引入sqlite
sqlite是纯c实现的,所以注定了它是一个跨平台利器,在android与ios下均能使用,而且完全可以写出通用的代码,方便我们移植。当然android和ios下都有封装过的sqlite给开发者使用,不过这样子一个是不方便移植,另一个是封装后的效率咋样我们也不知道,所以还是原生态的最健康。最后一个重要的原因就是原生的使用也是相当简单。我将在接下来的教程中为您一一讲解。
首先最重要的一点是在工程中导入sqlite,苹果的sdk已经给你包含进来了,所以只要导入一个叫 libsqlite3.0.dylib 的 framework就好了。然后,包含相应的头文件:#import "sqlite3.h" 。
在ios工程的导入就已经结束了,你可以正常使用了。
在其他工程中,比如android中,嵌入式linux中,我们就需要添加两个文件了 请到 http://sqlite.org/download.html 下载相应的文件,你用哪个平台的就对应下哪个文件,不过我一般下第一个叫做 sqlite-amalgamation-3071000.zip 的文件,这个里面包含了一个 sqlite3.c 与一个 sqlite3.h 。我直接把这两个文件拖到我的工程中去,然后在需要使用的地方把 .h 文件包含进来就好了 。这样比调用编译好的库的好处是我能更方便的调试,我也能对他的功能做一些修改,比如我可以自己在里面添加一套 自己的加密方式,又或者我可以添加几个回调函数来方便与上层交互。或者删掉我们不需要的功能,减少代码冗余。
在我接下来的讲解中,我会用纯c去讲解,虽然我会在苹果的 xcode 环境下去写代码,但是除了库的引用方式不一样以外,其他的都一样,我会尽量避免与平台相关的东西。当然有时候我可能会写一个有ui的demo,这时候就无可避免地要与平台打交道了,不过这个教程的关键点在于弄懂底层的原理,学会sqlite的api的调用,根据自己的需求封装以及提供接口。
最后附上xcode 中导入sqlite的图:
单击那个加号。然后搜索sqlite3 ,选取 sqlite3.0.dylib, 然后 单击add。然后你就看到工程中这个库导进来了。
然后在需要调用的地方导入头文件:
sqlite的数据类型
要使用数据库你得先弄清楚他的数据类型,不是吗?sqlite 数据类型及其简单:
- null. 空值
- integer. 整型
- real.浮点型
- text.文本类型
- blob. 二进制类型,用来存储文件,比如图片。
以上是sqlite的存储类型,当然,每种类型会根据数据长度有不同的子类型。这个现在不讲, 因为你可以直接使用上述这些大的类型。你知道知道有哪几个类型就好了。以后在实际运用中慢慢熟悉就好了 。
sqlite其实没有强制要求你预先声明数据类型,在实际存储过程中它会根据实际类型来自动转换,不过为了提高效率我们不建议non-datatype。
下面附上一个创建表的代码,主要是让你体会一下数据类型的实际运用:
1
2
3
4
5
6
|
create table student( name text, //姓名 no integer, //学号 totalscore real, //总分 photo blob //照片 ); |
句柄的定义
要操纵一个数据库你就得有一个这个数据库的句柄(又碰到这个难以理解的词了,不过确实还没得一个更好的词来替代它)。其实你跟本不需要去在乎这个词叫什么,你只要搞清楚他是一个什么玩意儿。就如同鞋子为什么叫鞋子,仔细想想确实也难以理解,不过 清楚他的功能就ok了,不是吗?
句柄在很多地方我们见到过,最常见的就是文件的句柄,我们要操纵一个文件,我们就要取得一个文件的句柄。句柄是个什么东东呢?其实很简单,句柄是一个东东的描述,他被定义为一个结构体,这个结构体可能会包含要描述的东东的具体信息,比如位置、大小、类型等等。我们有了这个描述信息我们就能去找到这个东东,然后操纵它。
一句话:句柄是物体的描述结构体。
我们来看看sqlite的句柄是怎么定义的(不要被吓到了,代码直接跳过就好):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
struct sqlite3 { sqlite3_vfs *pvfs; /* os interface */ int ndb; /* number of backends currently in use */ db *adb; /* all backends */ int flags; /* miscellaneous flags. see below */ unsigned int openflags; /* flags passed to sqlite3_vfs.xopen() */ int errcode; /* most recent error code (sqlite_*) */ int errmask; /* & result codes with this before returning */ u8 autocommit; /* the auto-commit flag. */ u8 temp_store; /* 1: file 2: memory 0: default */ u8 mallocfailed; /* true if we have seen a malloc failure */ u8 dfltlockmode; /* default locking-mode for attached dbs */ signed char nextautovac; /* autovac setting after vacuum if >=0 */ u8 suppresserr; /* do not issue error messages if true */ u8 vtabonconflict; /* value to return for s3_vtab_on_conflict() */ int nextpagesize; /* pagesize after vacuum if >0 */ int ntable; /* number of tables in the database */ collseq *pdfltcoll; /* the default collating sequence (binary) */ i64 lastrowid; /* rowid of most recent insert (see above) */ u32 magic; /* magic number for detect library misuse */ int nchange; /* value returned by sqlite3_changes() */ int ntotalchange; /* value returned by sqlite3_total_changes() */ sqlite3_mutex *mutex; /* connection mutex */ int alimit[sqlite_n_limit]; /* limits */ struct sqlite3initinfo { /* information used during initialization */ int idb; /* when back is being initialized */ int newtnum; /* rootpage of table being initialized */ u8 busy; /* true if currently initializing */ u8 orphantrigger; /* last statement is orphaned temp trigger */ } init; int nextension; /* number of loaded extensions */ void **aextension; /* array of shared library handles */ struct vdbe *pvdbe; /* list of active virtual machines */ int activevdbecnt; /* number of vdbes currently executing */ int writevdbecnt; /* number of active vdbes that are writing */ int vdbeexeccnt; /* number of nested calls to vdbeexec() */ void (*xtrace)( void *, const char *); /* trace function */ void *ptracearg; /* argument to the trace function */ void (*xprofile)( void *, const char *,u64); /* profiling function */ void *pprofilearg; /* argument to profile function */ void *pcommitarg; /* argument to xcommitcallback() */ int (*xcommitcallback)( void *); /* invoked at every commit. */ void *prollbackarg; /* argument to xrollbackcallback() */ void (*xrollbackcallback)( void *); /* invoked at every commit. */ void *pupdatearg; void (*xupdatecallback)( void *, int , const char *, const char *,sqlite_int64); #ifndef sqlite_omit_wal int (*xwalcallback)( void *, sqlite3 *, const char *, int ); void *pwalarg; #endif void (*xcollneeded)( void *,sqlite3*, int etextrep, const char *); void (*xcollneeded16)( void *,sqlite3*, int etextrep, const void *); void *pcollneededarg; sqlite3_value *perr; /* most recent error message */ char *zerrmsg; /* most recent error message (utf-8 encoded) */ char *zerrmsg16; /* most recent error message (utf-16 encoded) */ union { volatile int isinterrupted; /* true if sqlite3_interrupt has been called */ double notused1; /* spacer */ } u1; lookaside lookaside; /* lookaside malloc configuration */ #ifndef sqlite_omit_authorization int (*xauth)( void *, int , const char *, const char *, const char *, const char *); /* access authorization function */ void *pautharg; /* 1st argument to the access auth function */ #endif #ifndef sqlite_omit_progress_callback int (*xprogress)( void *); /* the progress callback */ void *pprogressarg; /* argument to the progress callback */ int nprogressops; /* number of opcodes for progress callback */ #endif #ifndef sqlite_omit_virtualtable hash amodule; /* populated by sqlite3_create_module() */ vtabctx *pvtabctx; /* context for active vtab connect/create */ vtable **avtrans; /* virtual tables with open transactions */ int nvtrans; /* allocated size of avtrans */ vtable *pdisconnect; /* disconnect these in next sqlite3_prepare() */ #endif funcdefhash afunc; /* hash table of connection functions */ hash acollseq; /* all collating sequences */ busyhandler busyhandler; /* busy callback */ int busytimeout; /* busy handler timeout, in msec */ db adbstatic[2]; /* static space for the 2 default backends */ savepoint *psavepoint; /* list of active savepoints */ int nsavepoint; /* number of non-transaction savepoints */ int nstatement; /* number of nested statement-transactions */ u8 istransactionsavepoint; /* true if the outermost savepoint is a ts */ i64 ndeferredcons; /* net deferred constraints this transaction. */ int *pnbytesfreed; /* if not null, increment this in dbfree() */ #ifdef sqlite_enable_unlock_notify /* the following variables are all protected by the static_master ** mutex, not by sqlite3.mutex. they are used by code in notify.c. ** ** when x.punlockconnection==y, that means that x is waiting for y to ** unlock so that it can proceed. ** ** when x.pblockingconnection==y, that means that something that x tried ** tried to do recently failed with an sqlite_locked error due to locks ** held by y. */ sqlite3 *pblockingconnection; /* connection that caused sqlite_locked */ sqlite3 *punlockconnection; /* connection to watch for unlock */ void *punlockarg; /* argument to xunlocknotify */ void (*xunlocknotify)( void **, int ); /* unlock notify callback */ sqlite3 *pnextblocked; /* next in list of all blocked connections */ #endif }; typedef struct sqlite3 sqlite3; // |
是不是被吓到了,没关系,这段代码本来就是我贴出来吓唬你的,我也没认真研究过这个代码,也不想去研究,除非哪天有人出高价请我去研究,我现在只知道怎么用就好了。
这个 sqlite3 结构体就是被用来描述我们磁盘里的数据库文件的,有了这个描述符我们就可以对这个数据库进行各种操作了,操作的具体内情我们不必要了解,我们只需要知道怎么去调用api就好了,当然有时候还是要了解一点点内情的,这个以后碰到再讲。
我用这么长的话加一大段吓人的代码只有一个目的:不要对句柄有恐惧感。
好了,开始我们的正题,sqlite 里面你要操纵数据库我们先得创建一个句柄,然后后面所有对数据库得操作都会用到这个句柄。
1
|
sqlite3* pdb; |
就 这么简单,这样一个ssqlite的句柄我们就创建完成了,我们以后针对数据库的操作都离不开它了。