code
insert SQL insert statements for TABLE
line One value per line
list Values delimited by .separator string
tabs Tab-separated values
tcl TCL list elements
.nullvalue STRING Print STRING in place of NULL values
.output FILENAME Send output to FILENAME
.output stdout Send output to the screen
.prompt MAIN CONTINUE Replace the standard prompts
.quit Exit this program
.read FILENAME Execute SQL in FILENAME
.schema ?TABLE? Show the CREATE statements
.separator STRING Change separator used by output mode and .import
.show Show the current values for various settings
.tables ?PATTERN? List names of tables matching a LIKE pattern
.timeout MS Try opening locked tables for MS milliseconds
.width NUM NUM ... Set column widths for "column" mode
sqlite>
这里看到的命令都
带有“.”开头,或者说sqlite下,只有这些命令是需要带“.”的。我们会经常用到的命令有:
.output FILENAME
.output stdout
.quit
.read FILENAME
.schema ?TABLE?
.dump ?TABLE? ...
.echo ON|OFF
.exit
在下面会涉及到这些具体内容的。我们慢慢来。
2.4 查看当前数据库下的所有表
当数据库越来越大时,我们也许并不太记得数据库中有多少个表了,这时就需要查看当前数据库下的有些什么表。
我们可以用 .tables 命令 。
sqlite> .tables
SensorData
sqlite>
2.5 退出sqlite3
对于初学者,也许不知道怎么安全退出,不过如果是从头看到此处的读者也许已经知道了,
因为刚才 .help 命令已经告诉我们答案了。安全退出有两个命令:.exit 和 .quit
好了,我们已经新建一个名为zieckey.db的数据库,并在其中新建一个名为 SensorData 的表.
现在我们想退出,那么可以用到刚刚提到的 .exit 和 .quit 命令。
例如我们可以这样退出:
sqlite> .exit
这里需要说明一下,如果不是用 .exit 和 .quit 这两个命令退出,我们对数据库的修改有可能丢失。
三、在Linux下用C/C++语言操纵SQLite数据库
1. 说明
这里我们假设你已经编译好了sqlite的库文件 :
libsqlite3.a https://www.doczj.com/doc/f912931473.html, libsqlite3.so libsqlite3.so.0 libsqlite3.so.0.8.6 pkgconfig
和可执行文件 : sqlite3
我们再假设你的sqlite3的安装目录在 /usr/local/sqlite3 目录下。
如果不是,我们可以这样做,将你的安装文件复制到 /usr/local/sqlite3 这个目录,
这样我们好在下面的操作中更加统一,从而减少出错的概率
例如:[root@localhost home]# cp -rf sqlite-3.3.8-ix86/ /usr/local/sqlite3
这里假设 /home/sqlite-3.3.8-ix86/ 是你的安装目录,也就是说你的sqlite原来就是安装在这里
这样之后,我们的sqlite3的库文件目录是:/usr/local/sqlite3/lib
可执行文件 sqlite3 的目录是: /usr/local/sqlite3/bin
头文件 sqlite3.h 的目录是: /usr/local/sqlite3/include
可以用ls命令查看下:
[root@localhost sqlite]# ls /usr/local/sqlite3/lib
libsqlite3.a https://www.doczj.com/doc/f912931473.html, libsqlite3.so libsqlite3.so.0 libsqlite3.so.0.8.6 pkgconfig
好拉,现在开始我们的Linux下sqlite3编程之旅。
2. 开始
这里我们现在进行一个测试。
现在我们来写个C/C++程序,调用 sqlite 的 API 接口函数。
下面是一个C程序的例 子,显示怎么使用 sqlite 的 C/C++ 接口. 数据库的名字由第一个参数取得且第二个参数或更多的参数是 SQL 执行语句. 这个函数调用sqlite3_open() 在 16 行打开数据库,并且sqlite3_close() 在 25 行关闭数据库连接。
[root@localhost temp]# vi opendbsqlite.c
按下 i 键切换到输入模式,输入下列代码:
// name: opendbsqlite.c
// This prog is used to test C/C++ API for sqlite3.It is very simple,ha!
// Author : zieckey
All rights reserved.
// date : 2006/11/13
#include
#include
int main( void )
{
sqlite3 *db=NULL;
char *zErrMsg = 0;
int rc;
//打开指定的数据库文件,如果不存在将创建一个同名的数据库文件
rc = sqlite3_open("zieckey.db", &db);
if( rc )
{
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return 0;
}
else printf("You have opened a sqlite3 database named zieckey.db successfully!\nCongratulations! Have fun ! ^-^ \n");
sqlite3_close(db); //关闭数据库
return 0;
}
退出,保存。(代码输入完成后,按下 Esc 键,然后输入: :wq ,回车就好拉)
好拉,现在编译:[root@localhost temp]# gcc opendbsqlite.c -o db.out
或者遇到这样的问题:
[root@localhost temp]# gcc opendbsqlite.c -o db.out
opendbsqlite.c:11:21: sqlite3.h: 没有那个文件或目录
opendbsqlite.c: In function `main':
opendbsqlite.c:19: `sqlite3' undeclared (first use in this function)
opendbsqlite.c:19: (Each undeclared identifier is reported only once
opendbsqlite.c:19: for each function it appears in.)
opendbsqlite.c:19: `db' undeclared (first use in this function)
这是由于没有找到头文件的原因。
也许会碰到类似这样的问题:
[root@localhost temp]# gcc opendbsqlite.c -o db.out
/tmp/ccTkItnN.o(.text+0x2b): In function `main':
: undefined reference to `sqlite3_open'
/tmp/ccTkItnN.o(.text+0x45): In function `main':
: undefined reference to `sqlite3_errmsg'
/tmp/ccTkItnN.o(.text+0x67): In function `main':
: undefined reference to `sqlite3_close'
/tmp/ccTkItnN.o(.text+0x8f): In function `main':
: undefined reference to `sqlite3_close'
collect2: ld returned 1 exit status
这是个没有找到库文件的问题。
下面我们着手解决这些问题。
由于用到了用户自己的库文件,所用应该指明所用到的库,我们可以这样编译:
[root@localhost temp]# gcc opendbsqlite.c -o db.out -lsqlite3
我用用 -lsqlite3 选项就可以了(前面我们生成的库文件是 libsqlite3.so.0.8.6 等,
去掉前面的lib和后面的版本标志,就剩下 sqlite3 了所以是 -lsqlite3 )。
如果我们在编译安装的时候,选择了安装路径,例如这样的话:
.......
# ../sqlite/configure --prefix=/usr/local/sqlite3
# make
.......
这样编译安装时,sqlite的库文件将会生成在 /usr/local/sqlite3/lib 目录下
sqlite的头文件将会生成在 /usr/local/sqlite3/include 目录下
这时编译还要指定库文件路径,因为系统默认的路径没有包含 /usr/local/sqlite3/lib
[root@localhost temp]# gcc opendbsqlite.c -o db.out -lsqlite3 -L/usr/local/sqlite3/lib
如果还不行的话,可能还需要指定头文件 sqlite3.h 的路径,如下:
[root@localhost temp]# gcc opendbsqlite.c -o db.out -lsqlite3 -L/usr/local/sqlite3/lib -I/usr/local/sqlite3/include
这样编译应该就可以了 ,运行:
[root@localhost temp]# ./db.out
./db.out:
error while loading shared libraries: libsqlite3.so.0: cannot open shared object file: No such file or directory
运行是也许会出现类似上面的错误。
这个问题因为刚刚编译的时候没有选择静态编译,那么按照默认的编译就动态编译的。
动态编译后,由于可执行文件在运行时要调用系统库文件,
那么沿着系统默认的库文件搜索路径搜索,就可能找不到我们现在所需的库文件。
致使出现 "error while loading shared libraries" 等错误。
我们可以这样解决:
方法一:静态编译
在编译时加上 -static 参数,例如
[root@localhost temp]# gcc opendbsqlite.c -o db.out -lsqlite3 -L/usr/local/sqlite3/lib -I/usr/local/sqlite3/include -static
[root@localhost temp]# ll
总用量 1584
-rwxr-xr-x 1 root root 1596988 11月 13 10:50 db.out
-rw-r--r-- 1 root root 614 11月 13 10:31 opendbsqlite.c
可以看到输出文件 db.out ,其大小为: 1596988k
运行,好了,没有出现错误
[root@localhost temp]# ./db.out
You have opened a sqlite3 database named zieckey.db successfully!
Congratulations! Have fun ! ^-^
方法二:重新配置系统环境变量 LD_LIBRARY_PATH
这时需要指定 libsqlite3.so.0 库文件的路径,也就是配置系统环境变量 LD_LIBRARY_PATH ,
使系统能够找到 libsqlite3.so.0 。
去掉 -static ,再编译:
[root@localhost temp]# gcc opendbsqlite.c -o db.out -lsqlite3 -L/usr/local/sqlite3/lib -I/usr/local/sqlite3/include
[root@localhost temp]# ll
总用量 36
-rwxr-xr-x 1 root root 12716 11月 13 10:56 db.out
-rw-r--r-- 1 root root 614 11月 13 10:31 opendbsqlite.c
[root@localhost temp]#
可以看到输出文件 db.out ,其大小为: 12716k,比刚才的静态编译要小得多。
所以我们推荐使用动态编译的方法。
好了,现在我们来指定系统环境变量 LD_LIBRARY_PATH 的值
在shell下输入:
[root@localhost temp]# export LD_LIBRARY_PATH=/usr/local/sqlite3/lib:$LD_LIBRARY_PATH
看看现在系统环境设置:
[root@localhost temp]#env
SSH_AGENT_PID=3511
HOSTNAME=localhost.localdomain
DESKTOP_STARTUP_ID=
SHELL=/bin/bash
TERM=xterm
HISTSIZE=1000
GTK_RC_FILES=/etc/gtk/gtkrc:/root/.gtkrc-1.2-gnome2
WINDOWID=29388238
OLDPWD=/mnt/usb/wuruan/sqlite
QTDIR=/usr/lib/qt-3.1
USER=root
LD_LIBRARY_PATH=/usr/local/sqlite3/lib:
LS_COLORS=no=00:fi=00:di=00;34:ln=00;36:pi=40;33:so=00;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=00;32:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=00;32:*.bat=00;32:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;31:*.tz=00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00;35:*.xpm=00;35:*.png=00;35:*.tif=00;35:
SSH_AUTH_SOCK=/tmp/ssh-XXt14q3a/agent.3456
SESSION_MANAGER=local/localhost.localdomain:/tmp/.ICE-unix/3456
USERNAME=root
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin
INPUTRC=/etc/inputrc
PWD=/mnt/usb/wuruan
XMODIFIERS=@im=fcitx
LANG=zh_CN.GB18030
GDMSESSION=Default
SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass
HOME=/root
SHLVL=2
LANGUAGE=zh_CN.GB18030:zh_CN.GB2312:zh_CN
GNOME_DESKTOP_SESSION_ID=Default
BASH_ENV=/root/.bashrc
LOGNAME=root
LESSOPEN=|/usr/bin/lesspipe.sh %s
DISPLAY=:0.0
G_BROKEN_FILENAMES=1
COLORTERM=gnome-terminal
XAUTHORITY=/root/.Xauthority
_=/bin/env
看到了吧,LD_LIBRARY_PATH这一行开始就是sqlite3的库文件路径:
LD_LIBRARY_PATH=/usr/local/sqlite3/lib: ............
好拉,现在再运行
[root@localhost temp]# ./db.out
You have opened a sqlite3 database named zieckey.db successfully!
Congratulations! Have fun ! ^-^
是不是很有成就感阿 ,呵呵,这个上手还是很快的。
3. 插入:insert
刚刚我们知道了怎么调用 sqlite3 的C/C++的API函数接口,下面我们看看怎么在C语言中向数据库插入数据。
好的,我们现编辑一段c代码,取名为 insert.c
// name: insert.c
// This prog is used to test C/C++ API for sqlite3 .It is very simple,ha !
// Author : zieckey All rights reserved.
// date : 2006/11/18
#include
#include
#include "sqlite3.h"
#define _DEBUG_
int main( void )
{
sqlite3 *db=NULL;
char *zErrMsg = 0;
int rc;
rc = sqlite3_open("zieckey.db", &db); //打开指定的数据库文件,如果不存在将创建一个同名的数据库文件
if( rc )
{
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return 0;
}
else printf("You have opened a sqlite3 database named zieckey.db successfully!\nCongratulations! Have fun ! ^-^ \n");
//创建一个表,如果该表存在,则不创建,并给出提示信息,存储在 zErrMsg 中
char *sql = " CREATE TABLE SensorData(
ID INTEGER PRIMARY KEY,
SensorID INTEGER,
SiteNum INTEGER,
Time VARCHAR(12),
SensorParameter REAL
);" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
#ifdef _DEBUG_
printf("%s\n",zErrMsg);
#endif
//插入数据
sql = "INSERT INTO \"SensorData\" VALUES( NULL , 1 , 1 , '200605011206', 18.9 );" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
sql = "INSERT INTO \"SensorData\" VALUES( NULL , 1 , 1 , '200605011306', 16.4 );" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
sqlite3_close(db); //关闭数据库
return 0;
}
好的,将上述代码写入一个文件,并将其命名为 insert.c 。
解释:
sqlite3_exec的函数原型说明如下:
int sqlite3_exec(
sqlite3*, /* An open database */
const char *sql, /* SQL to be executed */
sqlite_callback, /* Callback function */
void *, /* 1st argument to callback function */
char **errmsg /* Error msg written here */
);
编译:
[root@localhost temp]# gcc insert.c -lsqlite3 -L/usr/local/sqlite3/lib -I/usr/local/sqlite3/include
insert.c:28:21: warning: multi-line string literals are deprecated
[root@localhost temp]#
执行
[root@localhost temp]# ./a.out
./a.out: error while loading shared libraries: libsqlite3.so.0: cannot open shared object file: No such file or directory
[root@localhost temp]#
同样的情况,如上文处理方法:
[root@localhost temp]# export LD_LIBRARY_PATH=/usr/local/sqlite3/lib:$LD_LIBRARY_PATH
[root@localhost temp]# ./a.out
You have opened a sqlite3 database named zieckey.db successfully!
Congratulations! Have fun ! ^-^
(null)
(null)
(null)
[root@localhost temp]#
运行成功了,好了,现在我们来看看是否插入了数据
[root@localhost temp]# /usr/local/sqlite3/bin/sqlite3 zieckey.db
SQLite version 3.3.8
Enter ".help" for instructions
sqlite> select * from SensorData;
1|1|1|200605011206|18.9
2|1|1|200605011306|16.4
sqlite>
哈哈,已经插入进去了,不是吗?
很简单是不?
4. 查询: SELETE
好了,我们知道了怎么调用 sqlite3 的C/C++的API函数接口去创建数据库、创建表格、并插入数据,
下面我们看看怎么在C语言中查询数据库中的数据。
好的,我们现编辑一段c代码,取名为 query.c
// name: query.c
// This prog is used to test C/C++ API for sqlite3 .It is very simple,ha !
// Author : zieckey All rights reserved.
// date : 2006/11/18
#include
#include
#include "sqlite3.h"
#define _DEBUG_
int main( void )
{
sqlite3 *db=NULL;
char *zErrMsg = 0;
int rc;
rc = sqlite3_open("zieckey.db", &db); //打开指定的数据库文件,如果不存在将创建一个同名的数据库文件
if( rc )
{
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return 0;
}
else printf("You have opened a sqlite3 database named zieckey.db successfully!\nCongratulations! Have fun ! ^-^ \n");
//创建一个表,如果该表存在,则不创建,并给出提示信息,存储在 zErrMsg 中
char *sql = " CREATE TABLE SensorData(
ID INTEGER PRIMARY KEY,
SensorID INTEGER,
SiteNum INTEGER,
Time VARCHAR(12),
SensorParameter REAL
);" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
#ifdef _DEBUG_
printf("zErrMsg = %s \n", zErrMsg);
#endif
//插入数据
sql = "INSERT INTO \"SensorData\" VALUES(NULL , 1 , 1 , '200605011206', 18.9 );" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
sql = "INSERT INTO \"SensorData\" VALUES(NULL , 1 , 1 , '200605011306', 16.4 );" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
int nrow = 0, ncolumn = 0;
char **azResult; //二维数组存放结果
//查询数据
/*
int sqlite3_get_table(sqlite3*, const char *sql,char***result , int *nrow , int *ncolumn ,char **errmsg );
result中是以数组的形式存放你所查询的数据,首先是表名,再是数据。
n
row ,ncolumn分别为查询语句返回的结果集的行数,列数,没有查到结果时返回0
*/
sql = "SELECT * FROM SensorData ";
sqlite3_get_table( db , sql , &azResult , &nrow , &ncolumn , &zErrMsg );
int i = 0 ;
printf( "row:%d column=%d \n" , nrow , ncolumn );
printf( "\nThe result of querying is : \n" );
for( i=0 ; i<( nrow + 1 ) * ncolumn ; i++ )
printf( "azResult[%d] = %s\n", i , azResult[i] );
//释放掉 azResult 的内存空间
sqlite3_free_table( azResult );
#ifdef _DEBUG_
printf("zErrMsg = %s \n", zErrMsg);
#endif
sqlite3_close(db); //关闭数据库
return 0;
}
我们这里用到了一个查询的语句是 "SELECT * FROM SensorData " ,
在C语言中对应的函数接口是 sqlite3_get_table( db , sql , &azResult , &nrow , &ncolumn , &zErrMsg );
这个函数接口的解释在程序中已经注释。
下面我们编译运行下看看,
[root@localhost temp]# export LD_LIBRARY_PATH=/usr/local/sqlite3/lib:$LD_LIBRARY_PATH
[root@localhost temp]# gcc query.c -lsqlite3 -L/usr/local/sqlite3/lib -I/usr/local/sqlite3/include
query.c:29:21: warning: multi-line string literals are deprecated
[root@localhost temp]# ./a.out
You have opened a sqlite3 database named zieckey.db successfully!
Congratulations! Have fun ! ^-^
zErrMsg = (null)
row=2 column=5
The result of querying is :
azResult[0] = ID
azResult[1] = SensorID
azResult[2] = SiteNum
azResult[3] = Time
azResult[4] = SensorParameter
azResult[5] = 1
azResult[6] = 1
azResult[7] = 1
azResult[8] = 200605011206
azResult[9] = 18.9
azResult[10] = 2
azResult[11] = 1
azResult[12] = 1
azResult[13] = 200605011306
azResult[14] = 16.4
zErrMsg = (null)
这里我们可以看到,azResult 的前面 5 个数据正好是我们的表 SensorData 的列属性,
之后才是我们要查询的数据。所以我们的程序中才有 i<( nrow + 1 ) * ncolumn 的判断条件:
for( i=0 ; i<( nrow + 1 ) * ncolumn ; i++ )
printf( "azResult[%d] = %s\n", i , azResult[i] );
输出中有 zErrMsg = (null) 这样的字句,这是 zErrMsg 保留的错误信息,
正如你所看到的,zErrMsg 为空,表明在执行过程中没有错误信息。
5. 删除:delete
下面我们看看怎么在C语言中删除数据库中的特定的数据。
好的,我们现编辑一段c代码,取名为 delete.c
// name: delete.c
// This prog is used to test C/C++ API for sqlite3 .It is very simple,ha !
// Author : zieckey All rights reserved.
// date : 2006/11/18
#include
#include
#include "sqlite3.h"
#define _DEBUG_
int main( void )
{
sqlite3 *db=NULL;
char *zErrMsg = 0;
int rc;
rc = sqlite3_open("zieckey.db", &db); //打开指定的数据库文件,如果不存在将创建一个同名的数据库文件
if( rc )
{
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return 0;
}
else printf("You have opened a sqlite3 database named zieckey.db successfully!\nCongr
atulations! Have fun ! ^-^ \n");
//创建一个表,如果该表存在,则不创建,并给出提示信息,存储在 zErrMsg 中
char *sql = " CREATE TABLE SensorData(
ID INTEGER PRIMARY KEY,
SensorID INTEGER,
SiteNum INTEGER,
Time VARCHAR(12),
SensorParameter REAL
);" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
#ifdef _DEBUG_
printf("zErrMsg = %s \n", zErrMsg);
#endif
//插入数据
sql = "INSERT INTO \"SensorData\" VALUES(NULL , 1 , 1 , '200605011206', 18.9 );" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
sql = "INSERT INTO \"SensorData\" VALUES(NULL , 23 , 45 , '200605011306', 16.4 );" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
sql = "INSERT INTO \"SensorData\" VALUES(NULL , 34 , 45 , '200605011306', 15.4 );" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
int nrow = 0, ncolumn = 0;
char **azResult; //二维数组存放结果
//查询数据
sql = "SELECT * FROM SensorData ";
sqlite3_get_table( db , sql , &azResult , &nrow , &ncolumn , &zErrMsg );
int i = 0 ;
printf( "row:%d column=%d \n" , nrow , ncolumn );
printf( "\nThe result of querying is : \n" );
for( i=0 ; i<( nrow + 1 ) * ncolumn ; i++ )
printf( "azResult[%d] = %s\n", i , azResult[i] );
//删除数据
sql = "DELETE FROM SensorData WHERE SensorID = 1 ;" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
#ifdef _DEBUG_
printf("zErrMsg = %s \n", zErrMsg);
#endif
sql = "SELECT * FROM SensorData ";
sqlite3_get_table( db , sql , &azResult , &nrow , &ncolumn , &zErrMsg );
printf( "\n\n\n\nrow:%d column=%d " , nrow , ncolumn );
printf( "\nAfter deleting , the result of querying is : \n" );
for( i=0 ; i<( nrow + 1 ) * ncolumn ; i++ )
printf( "azResult[%d] = %s\n", i , azResult[i] );
//释放掉 azResult 的内存空间
sqlite3_free_table( azResult );
#ifdef _DEBUG_
printf("zErrMsg = %s \n", zErrMsg);
#endif
sqlite3_close(db); //关闭数据库
return 0;
}
下面我们编译运行看看,效果如何
[root@localhost temp]# export LD_LIBRARY_PATH=/usr/local/sqlite3/lib:$LD_LIBRARY_PATH
[root@localhost temp]# gcc delete.c -lsqlite3 -L/usr/local/sqlite3/lib -I/usr/local/sqlite3/include
delete.c:29:21: warning: multi-line string literals are deprecated
[root@localhost temp]# ./a.out
You have opened a sqlite3 database named zieckey.db successfully!
Congratulations! Have fun ! ^-^
zErrMsg = (null)
row=3 column=5
The result of querying is :
azResult[0] = ID
azResult[1] = SensorID
azResult[2] = SiteNum
azResult[3] = Time
azResult[4] = SensorParameter
azResult[5] = 1
azResult[6] = 1
azResult[7] = 1
azResult[8] = 200605011206
azResult[9] = 18.9
azResult[10] = 2
azResult[11] = 23
azResult[12] = 45
azResult[13] = 200605011306
azResult[14] = 16.4
azResult[15] = 3
azResult[16] = 34
azResult[17] = 45
azResult[18] = 200605011306
azResult[19] = 15.4
zErrMsg = (null)
row:2 column=5
After deleting , the result of querying is :
azResult[0] = ID
azResult[1] = SensorID
azResult[2] = SiteNum
azResult[3] = Time
azResult[4] = SensorParameter
azResult[5] = 2
azResult[6] = 23
azResult[7] = 45
azResult[8] = 200605011306
azResult[9] = 16.4
azResult[10] = 3
azResult[11] = 34
azResult[12] = 45
azResult[13] = 200605011306
azResult[14] = 15.4
zErrMsg = (null)
从程序输出结果就可以看出,在删除数据前,我们有三条记录,
删除数据后我们发现,数据库内记录少了。从而实现了我们的删除数据目的。
总结:
在这篇文章里,我们主要了解了SQLite数据库的一些特性,并且在Linux下的编译安装方法,
同时我们还了解了如何使用SQLite数据库,包括通过SQL语句和编程来实现对数据库的数据管理。
在程序中对数据库管理的是在C/C++语言中调用 sqlite 的函数接口来实现对数据库的管理,
包括创建数据库、创建表格、插入数据、查询数据、删除数据等。而这些操作似乎都很简单不是吗?
几天为了解决openfetion登录速度过慢的问题,决定实现数据的 本地化功能,以往采用二进制文件直接写入磁盘的形式效率和灵活性显然远远不够,于是毅然决定采用sqlite3来实现,用过之后才发现sqlite3果然 是绝佳的选择,作为一种轻量型的数据库,sqlite3有着它独特的优势,简单易用,而且极为高效,当初在引入这个依赖库的时候还在犹豫,但完成后发现它 所带来的用户体验绝对可以掩盖住安装时多一个小步骤的繁琐。
sqlite3第一次用,简单地把自己的使用过程写一下,以后再用到可以参考。
sqlite3对很多通过的SQL语句都支持,像SELECT,UPDATE,INSERT,DELETE等等都支持地很好,只要懂SQL语句就可以用sqlite3。
1,下面是几个比较重要的API函数:
/* 打开数据库,如果不存在则创建一个 */
int sqlite3_open(const char*, sqlite3**);
/* 关闭数据库 */
int sqlite3_close(sqlite3*);
/* 获取错误信息字符串 */
const char *sqlite3_errmsg(sqlite3*);
/* 执行SQL语句 */
int sqlite3_exec(sqlite3*, const char *sql, sqlite_callback, void*, char**);
/* 获取SQL查询结果,其实这个函数是不推荐使用的,一方面是因为它不安全,另一方面它不能处理BLOG类型的字段,当然,在这里我在查询的时候还是使用了它,因为没有涉及到多复杂多庞大的数据,这个使用起来又简单,所以就选用了这个方法 */
int sqlite3_get_table(
sqlite3 *db, /* An open database */
const char *zSql, /* SQL to be evaluated */
char ***pazResult, /* Results of the query */
int *pnRow, /* Number of result rows written here */
int *pnColumn, /* Number of result columns written here */
char **pzErrmsg /* Error msg written here */
);
还有复杂一些的API如下,我没仔细看,像sqlite3_get_table这
些函数就是由下面这些API组合而成的
INT sqlite3_prepare(sqlite3*, const CHAR*, INT, sqlite3_stmt**, const CHAR**);
INT sqlite3_bind_double(sqlite3_stmt*, INT, DOUBLE);
INT sqlite3_bind_int(sqlite3_stmt*, INT, INT);
INT sqlite3_bind_int64(sqlite3_stmt*, INT, long long INT);
INT sqlite3_bind_null(sqlite3_stmt*, INT);
INT sqlite3_bind_text(sqlite3_stmt*, INT, const CHAR*, INT n, void(*)(void*));
INT sqlite3_bind_text16(sqlite3_stmt*, INT, const void*, INT n, void(*)(void*));
INT sqlite3_step(sqlite3_stmt*);
2,创建自增长类型的字段
CREATE TABLE history (id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,userid TEXT,message TEXT,
updatetime TEXT,issend INTEGER);
这个语句中创建的id字段即为自增长的字段,在插入记录的时候只需把id字段写为NULL即可实现其自增长,如:
INSERT INTO history VALUES(NULL,"levin","123456","hello sqlite3","2010-10-23",1);
3.sqlite3的限制读取条数
/* 在其它SQL数据库中SELECT指定条数的记录用如下语句:*/
SELECT TOP 10 * FROM history;
/* 而在sqlite3中使用下面语句:*/
SELECT * FROM history LIMIT 10
4.sqlite3的日期函数
sqlite3的日期函数还是很强大的,列举几个常用的。
/* 获取当前时间 */
SELECT DATETIME('now')
输出:2010-10-23 12:10:50
/* 获取当前时间偏移 */
SELECT DATETIME('now','+20 days');
输出:2010-11-12 12:12:54
/* 获取今年开始时间 */
SELECT DATETIME('now','start of year');
输出:2010-01-01 00:00:00
/* 获取本月开始时间 */
SELECT DATETIME('now','start of month');
输出:2010-10-01 00:00:00
/* 获取今天开始时间 */
SELECT DATETIME('now','start of day');
输出:2010-10-23 00:00:00
另外,sqlite3里面有个很重要的时间函数,strftime,这个跟POSIX里面的strftime函数很像,也是将日期类型格式化为字符串类型,如:
SELECT strftime('%Y|%m|%d','now');
2010|10|23
它的格式化字符和POSIX的strftime也完全一样,再例如我要查询本月的聊天记录,可以使用下面语句:
SELECT * FROM history WHERE
strftime('%Y',updatetime) == strftime('%Y','now') AND
strftime('%m',updatetime) == strftime('%m','now') ;
5.写入较大数据时采用事务提高效率
我在应用sqlite3的时候其实只是写入了少量的数据,刚开始觉得效率不是什么大问题,后来有用户反馈说他的290+好友的飞信号在登录时要向磁盘写入几十S的数据,这个效率问题着实需要改善,于是采用事务来处理写入,事务的使用也非常简单,其实也就是下面的语句:
sqlite3_exec(db, "BEGIN TRANSACTION;", 0,0, &errMsg);
for(;;){
insert into.....
}
sqlite3_exec(db, "COMMIT TRANSACTION;", 0, 0, &errMsg);
这样一系列地插入语句就可以被作为一个事务来执行,在COMMIT TRANSACTION的时候将插入操作写入磁盘,避免了每次插入记录时频繁地读写磁盘数据库,从而使效率
大大提高,据说可以比单纯地插入快1000倍, 这个我无从考证,不过我这里确实快了很多,几百条记录可以瞬间写入。
就在昨天一本科同学还问我会不会sqlite,我正好前两天也用了,就跟她交流了下,她问我怎么写入多条数据,呃..这个问题很简单,就是循环,在 程序里面循环,想在SQL里面循环用sqlite3是做不到的,因为sqlite3忽略了很多数据库很重要的特性,它不支持存储过程,而且也没有其它数据 库地高并发性,因此有的时候我多个线程同时访问同一个数据库文件的时候,便会报错说database is locked。
OK,以上只是我个人使用过程中的一点小小地总结,拿过来就用,也没做多少研究,sqlite3一些复杂的机制都没有去了解,把这些基础的东西写下来,给自己做个备份,说不定哪天还会再用到。
原创文章,转载请注明: 转载自basic coder
本文链接地址: https://www.doczj.com/doc/f912931473.html,/sqlite3-usage.html
Sqlite3简单介绍与一些常用的例子
博客分类:
? iphone
Sqlite3简单介绍与一些常用的例子
转载自 https://www.doczj.com/doc/f912931473.html,/6905346.html
1:常用接口
个人比较喜欢sqlite, 使用最方便,唯一的准备工作是下载250K的源;而且作者很热心,有问必答。
以下演示一下使用sqlite的步骤,先创建一个数据库,然后查询其中的内容。2个重要结构体和5个主要函数:
sqlite3 *pdb, 数据库句柄,跟文件句柄FILE很类似
sqlite3_stmt *stmt, 这个相当于ODBC的Command对象,用于保存编译好的SQL语句
sqlite3_open(), 打开数据库
sqlite3_exec(), 执行非查询的sql语句
sqlite3_prepare(), 准备sql语句,执行select语句或者要使用parameter bind时,用这个函数(封装了sqlite3_exec).
Sqlite3_step(), 在调用sqlite3_prepare后,使用这个函数在记录集中移动。
Sqlite3_close(), 关闭数据库文件
还有一系列的函数,用于从记录集字段中获取数据,如
sqlite3_column_text(), 取text类型的数据。
sqlite3_column_blob(),取blob类型的数据
sqlite3_column_int(), 取int类型的数据
…
2:sqlite数据类型介绍
在进行数据库Sql操作之前,首先有个问题需要说明,就是Sqlite的数据类型,和其他的数据库不同,Sqlite支持的数据类型有他自己的特色,这个特色有时会被认为是一个潜在的缺点,但是这个问题并不在我们的讨论范围之内。
大 多数的数据库在数据类型上都有严格的限制,在建立表的时候,每一列都必须制定一个数据类型,只有符合该数据类型的数据可以被保存在这一列当中。而在 Sqlite 2.X中,数据类型这个属性只属于数据本生,而不和数据被存在哪一列有关,也就是说数据的类型并不受数据列限制(有一个例外:INTEGER PRIMAR
Y KEY,该列只能存整型数据)。
但是当Sqlite进入到3.0版本的时候,这个问题似乎又有了新的答案,Sqlite的开发者 开始限制这种无类型的使用,在3.0版本当中,每一列开始拥有自己的类型,并且在数据存入该列的时候,数据库会试图把数据的类型向该类型转换,然后以转换 之后的类型存储。当然,如果转换被认为是不可行的,Sqlite仍然会存储这个数据,就像他的前任版本一样。
举个例子,如果你企图向一个INTEGER类型的列中插入一个字符串,Sqlite会检查这个字符串是否有整型数据的特征, 如果有而且可以被数据库所识别,那么该字符串会被转换成整型再保存,如果不行,则还是作为整型存储。
总的来说,所有存在Sqlite 3.0版本当中的数据都拥有以下之一的数据类型:
空(NULL):该值为空
整型(INTEGEER):有符号整数,按大小被存储成1,2,3,4,6或8字节。
实数(REAL):浮点数,以8字节指数形式存储。
文本(TEXT):字符串,以数据库编码方式存储(UTF-8, UTF-16BE 或者 UTF-16-LE)。
BLOB:BLOB数据不做任何转换,以输入形式存储。
ps: 在关系数据库中,CLOB和BLOB类型被用来存放大对象。BOLB表示二进制大对象,这种数据类型通过用来保存图片,图象,视频等。CLOB表示字符大对象,能够存放大量基于字符的数据。
对应的,对于数据列,同样有以下的数据类型:
TEXT
NUMERIC
INTEGER
REAL
NONE
数据列的属性的作用是确定对插入的数据的转换方向:
TEXT 将数据向文本进行转换,对应的数据类型为NULL,TEXT 或 BLOB
NUMERIC 将数据向数字进行转换,对应的数据类型可能为所有的五类数据,当试图存入文本 时将执行向整型或浮点类型的转换(视具体的数值而定),转换若不可行,则保留文本类型存储,NULL或BLOB不做变化
INTEGER 将数据向整型转换,类似于NUMERIC,不同的是没有浮点标志的浮点数将转换为整型保存
REAL 将数据向浮点数类型转换,类似于NUMERIC,不同的是整数将转换为浮点数保存
NULL 不做任何转换的数据列类型
实例代码如下,
附件工程可直接编译,例子使用了blob数据类型。
#include "sqlite3.h" //包含一个头文件就可以使用所以sqlite的接口了
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#pragma comment(lib, "sqlite.lib") //我把sqlite编译成了一个静态的lib文件。
void createdb();
void querydb();
int main()
{
createdb();
querydb();
return 0;
}
void createdb()
{
nt ret;
sqlite3 *pdb = 0;
sqlite3_stmt *stmt = 0;
char *error = 0;
char *sql = "insert into table1 values('value11',:aaa)";
int &nbs; index;
static void *value = "asdfadsfasdfjasdfjaksdfaskjdfakdsfaksfja";
ret = sqlite3_open("db1.sdb", &pdb); //打开数据库,跟打开文本文件一样
if( ret != SQLITE_OK )
return;
ret = sqlite3_exec(pdb, "create table table1(col1 char(20), col2 BLOB)", 0,0, &error );
if( ret != SQLITE_OK )
return;
ret = sqlite3_prepare(pdb, sql,strlen(sql), &stmt, &error);
if( ret != SQLITE_OK )
return;
index = sqlite3_bind_parameter_index(stmt, ":aaa");
ret = sqlite3_bind_blob(stmt, index, value, strlen(value), SQLITE_STATIC);
if( ret != SQLITE_OK )
return;
ret = sqlite3_step(stmt);
if( ret != SQLITE_DONE )
return;
sqlite3_close(pdb);
}
void querydb()
{
int ret;
sqlite3 *pdb = 0;
sqlite3_stmt *pstmt = 0;
char *error = 0;
char *sql = "select * from table1";
int len;
int i;
char *name;
void *value;
ret = sqlite3_open("db1.sdb", &pdb);
if( ret != SQLITE_OK )
return;
ret = sqlite3_prepare(pdb, sql, strlen(sql), &pstmt, &error);
if( ret != SQLITE_OK )
return;
while( 1 )
{
ret = sqlite3_step(pstmt);
if( ret != SQLITE_ROW )
break;
name = sqlite3_column_text(pstmt, 0);
value = sqlite3_column_blob(pstmt, 1);
len = sqlite3_column_bytes(pstmt,1 );
}
}
实例二:SQLite中如何用api操作blob类型的字段
在实际的编程开发当中我们经常要处理一些大容量二进制数据的存储,如图片或者音乐等等。对于这些二进制数据(blob字段)我们不能像处理普通的文本那样 简单的插入或者查询,为此SQLite提供了一组函数来处理这种BLOB字段类型。下面的代码演示了如何使用这些API函数。
首先我们要建立一个数据库:
sqlite3_exec(db, "CREATE TABLE list (fliename varchar(128) UNIQUE, fzip blob);", 0, 0, &zErrMsg);
//由于mmmm.rar是一个二进制文件,所以要在使用insert语句时先用?号代替
sqlite3_prepare(db, "insert into list values ('mmmm.rar',?);", -1, &stat, 0);
FILE *fp;
long filesize = 0;
char * ffile;
fp = fopen(
"mmmm.rar", "rb");
if(fp != NULL)
{
//计算文件的大小
fseek(fp, 0, SEEK_END);
filesize = ftell(fp);
fseek(fp, 0, SEEK_SET);
//读取文件
ffile = new char[filesize+1];
size_t sz = fread(ffile, sizeof(char), filesize+1, fp);
fclose(fp);
}
//将文件数据绑定到insert语句中,替换“?”部分
sqlite3_bind_blob(stat, 1, ffile, filesize, NULL);
//执行绑定之后的SQL语句
sqlite3_step(stat);
这时数据库当中已经有了一条包含BLOB字段的数据。接下来我们要读取这条数据:
//选取该条数据
sqlite3_prepare(db, "select * from list;", -1, &stat, 0);
sqlite3_step(stat);
//得到纪录中的BLOB字段
const void * test = sqlite3_column_blob(stat, 1);
//得到字段中数据的长度
int size = sqlite3_column_bytes(stat, 1);
//拷贝该字段
sprintf(buffer2, "%s", test);
此时可以将buffer2写入到文件当中,至此BLOB数据处理完毕。
实例三:sqlite 中用blob存储图片和取出图片
#include
#include
#include
using namespace std;
int main()
{
sqlite3 *db;
sqlite3_stmt *stat;
char *zErrMsg = 0;
char buffer2[1024]="0";
sqlite3_open("./MetaInfo.db", &db);
int result;
if(result)
{
cout<<"Open the database sqlite.db failed"<}
else
cout<<"Open the database sqlite.db sucessfully"<sqlite3_exec(db, "CREATE TABLE list (fliename varchar(128) UNIQUE, fzip blob);", 0, 0, &zErrMsg);
sqlite3_prepare(db, "insert into list values ('./data/2.bmp',?);", -1, &stat, 0);
FILE *fp;
long filesize = 0;
char * ffile;
fp = fopen("./data/2.bmp", "rb");
if(fp != NULL)
{
fseek(fp, 0, SEEK_END);
filesize = ftell(fp);
fseek(fp, 0, SEEK_SET);
ffile = new char[filesize+1];
size_t sz = fread(ffile, sizeof(char), filesize+1, fp);
fclose(fp);
}
sqlite3_bind_blob(stat, 1, ffile, filesize, NULL);
sqlite3_step(stat);
sqlite3_prepare(db, "select * from list;", -1, &stat, 0);
sqlite3_step(stat);
const void * test = sqlite3_column_blob(stat, 1);
int size = sqlite3_column_bytes(stat, 1);
sprintf(buffer2, "%s", test);
FILE *fp2;
fp2 = fopen("outfile.png", "wb");
if(fp2 != NULL)
{
size_t ret = fwrite(test, sizeof(char), size, fp2);
fclose(fp2);
}
delete(ffile);
sqlite3_finalize(stat);
sqlite3_close(db);
return 0;
}