sqllite3

本文详细介绍了在Ubuntu系统中如何管理SQLite数据库,包括安装SQLite、删除软件、使用命令行操作SQLite数据库(如创建、查询、删除表)以及SQLite3的高级特性,如模式匹配、输出格式设置和SQL解释器的使用。此外,还涵盖了C/C++环境下SQLite的编译和API调用,以及Windows环境下SQLite动态库的生成和使用。
摘要由CSDN通过智能技术生成

ubuntu删除软件

通用删除语法
dpkg --list//列出已安装的软件
sudo apt-get remove virtualbx&& sudo apt-get autoremove
  完整删除语法
    1、sudo apt-get --purge remove package_name
    2、sudo apt-get --purge remove virtualbox

sqllite3

1.介绍:sqlite3是linux上的小巧的数据库,一个文件就是一个数据库。
2.安装:
要安装sqlite3,可以在终端提示符后运行下列命令:
sudo apt-get install sqlite3
检查版本
sqlite3 -version
3.测试
当前目录下建立test.db测试数据库文件
sqlite3 test.db
查询信息
.database
退出
.exit

比较有用的命令

.table 显示数据库中所有的表
.schema 显示所有的表的创建语句
.schema tablename 显示表的创建语句
.quit退出

开始

      启动sqlite3程序,仅仅需要敲入带有SQLite数据库名字的"sqlite3"命令即可。如果文件不存在,则创建一个新的(数据库)文件。然后 sqlite3程序将提示你输入SQL。敲入SQL语句(以分号“;”结束),敲回车键之后,SQL语句就会执行。

        例如,创建一个包含一个表"tb11"名字为"ex1"的SQLite数据库,你可以这样做:

$sqlite3 ex1

SQLite数据库的框架被保存在一个名叫"sqlite_master"的特殊的表中。你可以像查询其它表一样通过执行“SELECT”查询这个特殊的表。例如:
select * from sqlite_master;

EMPORARY表的结构没有存储在"sqlite_master"表中,由于TEMPORARY表对应用是不可见的,而不是应用程序创建这个表。 TEMPORARY表结构被存储在另外一个名叫"sqlite_temp_master"的特定的表中。"sqlite_temp_master"表是临 时表自身。

sqlite3的特殊命令

大多数候,sqlite3读入输入行,并把它们传递到SQLite库中去运行。但是如果输入行以一个点(“.”)开始,那么这行将被sqlite3程序自 己截取并解释。这些“点命令”通常被用来改变查询输出

的格式,或者执行鞭个预封包(预定义prepackaged)的查询语句。

sqlite>

改变输出格式

​ sqlite3程序可以以八种不同的格式显示一个查询的结果:“csv”, “列”, “html”, “插入”, “行”, “制表"和"tcl”。你可以用".mode"点命令在这些输出格式之间切换。

​ 默认的输出格式是“列表”。在列表模式下,每条查询结果记录被写在一行中并且每列之间以一个字符串分割符隔开。默认的分隔符是一个管道符号(“|”)。列表符号在当你输出查询结果到另外一个符加处理的程序(如AWK)中去是尤为有用。
​ sqlite> .mode list

sqlite> select * from tbl1;

hello|10

goodbye|20

sqlite>

​ 你可以用“.separator”点命令来改变分界符。例如,为了把分割符改为一个逗号和一个空格,你可以这样做:

sqlite> .separator ", "

sqlite> select * from tbl1;

​ 在“line"模式下,每一个位于条记录中的列在它自己那行显示。每行由列名、一个等号和列数据组成。下一条记录以一个空行隔开。这是一个行模式输出的例子:

​ 在列模式下,每条记录在一个单独的行中以数据列对齐的方式显示。列如:

sqlite> .mode column

sqlite> select * from tbl1;

​ 在默认的情况下,每列至少10个字符宽。太宽的数据将被截取。你可以用“.width”命令来调整列宽。如下所示:

sqlite> .width 12 6

sqlite> select * from tbl1;

另外一个有用的输出模式是"insert"。在插入模式下,被子格式化为看起来像SQL INSERT语句的样式。你可以用插入模式来产生文件(便于)以后用于不同数据库的输入。

​ 当指定插入模式时,你必须给定一个特定参数就是要插入的表名。例如:

sqlite> .mode insert new_table

sqlite> select * from tbl1;

INSERT INTO ‘new_table’ VALUES(‘hello’,10);

INSERT INTO ‘new_table’ VALUES(‘goodbye’,20);

最新的输出格式是“html”。在这种模式下,sqlite3把查询的结果写做XHTML表。开始的

和结束 的
(标记)没有写出,但有、和等分界符。html输出对 CGI来说是相当有用地。

把结果写到文件中

​ 默认情况下,sqlte3把结送到标准输出。你可以用“.output”命令改变它。只须把输出文件名做为.output命令的输出参数然后所有后续查询结果将被写到那个文件中。用“.output stdout”再一次改为标准输出。例如:

查询数据库结构

​ sqlite3程序提供几个有用的用于查询数据库结构的快捷命令。这些不是不可以用别的方式来实现。这些命令仅仅是一个快捷方式而已。

​ 例如,为了查看数据库的表列表,你可以敲入“.tables”。

sqlite> .tables

tbl1

tbl2

sqlite>

​ “.tables”命令相似于设置列表模式然后执行接下来的查询:

SELECT name FROM sqlite_master WHERE type IN (‘table’,‘view’) AND name NOT LIKE 'sqlite_%'UNION ALL SELECT name FROM sqlite_temp_master WHERE type IN (‘table’,‘view’) ORDER BY 1sqlite> .schema

create table tbl1(one varchar(10), two smallint)

CREATE TABLE tbl2 (

f1 varchar(30) primary key,

f2 text,

f3 real

)

sqlite> .schema tbl2

CREATE TABLE tbl2 (

f1 varchar(30) primary key,

f2 text,

f3 real

)

sqlite>

事实上,你可以查看sqlite3的源代码(可以在源文件树的src/shell.c中),你可找到上面的具体的查询。

“.indices”命令作

“.indices”命令作用类似的方 式是列出特定表的所有的索引。“.indics”命令须一个参数即所要索引表的表名。最后,但不是至少,是“.schema”命令。不带任何参 数,“.schema”命令显示原始的用于创建当前数据库的CREATE TABLE和CREATE INDEX语句。如果你给".schema"命令一个表名,它显示原始的创建该表和它所有索引的CREATE语句。我们可以:

".schema"命令可以用设置列表然后执行以下查询来实现:

SELECT sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master)WHERE type!='meta’ORDER BY tbl_name, type DESC, name

或者,如果你给".schema"命令一个参数,由于你只想得到一个表的结构,查询可以是这样:

你可以担供一个参数给.schema命令。如果这橛,查询可以是这样的:

SELECT sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master)WHERE tbl_name LIKE ‘%s’ AND type!=‘meta’ AND sql NOT NULL AND name NOT LIKE 'sqlite_%'ORDER BY substr(type,2,1), name

在查询中“%S“为你的参数所取代。这使你可以询数据库结构的某个子集。

sqlite> .schema %abc%

与这些一起,“.table”命令也接受一个模式作为他的参数。如果你给“.table”一个参数,“%”将被前后扩展并且一个LIKE子句被附加到查询上。这让你可以列出只与特定模式相匹配的的表。

“.datebasae”命令显示所有 当前连接打开的数据库的一个列表。将允许一次到少两个。第一个是“main”,最初打开的那个数据库。第二个是"temp",用于临时表的数据库。对于用 ATTACH语句附加的数据也许有附加数据库列表。输出的第一列与之相联的数据库名,第二列是外部文件名。

sqlite> .databases

将整个数据库转换为ASCII文本文件

".dump"命令成一个单一的ASCII文本文件。这个文件可以被用作管道传递给sqlite3命令来转换回数据库。

一个最好的制作一个数据库档案拷贝的命令是:

echo '.dump'|sqlite3 ex1|gzip -c > ex1.dump.gz
重构数据库
zcat ex1.dump.gz|sqlite3 ex2
这个文本格式是纯粹的sql语句,所以你可以用.dump命令来导出一个sqlite数据库到另一个常用的sql数据库引擎
比如
createdb ex2
sqlite3 exe1 .dump|psql ex2

".explain"命令可以被用来设 置输出格式为“column” 并设置列宽为EXPLAIN命令看起来比较合理的宽度。EXPLAIN命令是SQLite特有的SQL扩展,它是对调试有用。如果任何常规的SQL被 EXPLAIN执行,那么SQL命令被分解并分析但并不执行。取而代之的是,虚拟机指令序列将被用于执行SQL命令并返回一个类似的查询结果。如:

sqlite> .explain

sqlite> explain delete from tbl1 where two<20;
“.timeout”命令设置sqlite3等待一个试图存储文件锁定请除直到错误返回的总时间。默认的超时值是0因此如果任何需要的数据库表或序列列被锁定时它将立即返回一个错误。

最后,我们提到“.exit”命令它交导致sqlite3退出。

在命令和脚本中使用sqlite3
一个在脚本命令中使用 sqlite3的方式是用“echo”或“cat”来产生一个命令序列在一个文件中,然后当从一个产生的命令行中重定向输入时调用sqlite3。它有用 并且适应许多环境。但作为一附加的便利是,sqlite3允许一个单一的SQL语句在命令行中作为数据库名后的第二个参数输入。当sqlite3程序带着 两个参数启动时,第二个参数被传递给SQLite库处理,查询以列表模式打印到标准输出,然后程序退出。这个机制被设计用于让sqlite3容易于用于连 接诸如"AWK"的程序。例如:

sqlite3 ex1 'select * from tb11'|>
awk '{print "<tr><td>%s<td>%s/n",$1,$2}'<tr><td>hello<td>10<tr><td>goodbye<td>20$
结束命令行命令

结束命令行命令

SQLite命令通常以一个分 号结束。在一个命令行中你也可以用“GO”单词(大小写敏感)或者一个“/”斜线在它所在好行结束一个命令。这常被SQL Server和Oracle使用。这些将不在sqlite3_exec()中有用,因为命令行在传递它们到函数之前把这些翻译为分号。

从源文件中编译sqlite3

sqlite3程序当你编译SQLite库时自动被建立。只须取得一个源文件树的拷贝,运行“configure"然后"make"即可。

文件迁移

c/c++开发

Windows
在SQLite官网下载二进制文件和源码的压缩包
在命令行使用
lib /DEF:sqlite3.def /MACHINE:X86
现在,我们已经得到了sqlite3.dll , sqlite3.lib和sqlite3.h,就可以正常的调用sqlite3 中的 API 函数了。(注:不再需要 sqlite.def 这个文件)
未找到sqlite.h
重新下载
http://www.sqlite.org/download.html,下载
sqlite-amalgamation-3190000.zip
sqlite-dll-win64-x64-3190000.zip(我下载的是64位。)
二、编译过程
1、打开VC新建一个 Win32 DLL 空工程,命名为 sqlite3
2、解压sqlite-amalgamation-X.zip,把sqlite3.h、sqlite3ext.h、sqlite3.c添加到工程项目中

3、修改配置,在项目属性,常规下的配置类型,将动态库(.dll)改成静态库(.lib)

4、编译,然后在编译目录中找到sqlite3.lib
————————————————
版权声明:本文为CSDN博主「zhangbohh8662」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zhangbohh8662/article/details/72644372
当然也可以通过dll-win64-x64中的sqlite3.dll获得sqlite3.lib 方法如下:

下面就说说如何将sqlite3.def转化为sqlite3.lib,这个法子同样适用于将其他def文件转化为lib文件,具体步骤如下:

打开VS中的命令管理器,输入指令

C:\ProgramFiles\Microsoft Visual Studio\VC98\Bin>LIB.EXE /MACHINE:X86 /DEF:sqlite3.def
————————————————
版权声明:本文为CSDN博主「zhangbohh8662」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zhangbohh8662/article/details/72644372
后续配置工作
将*.dll文件拷贝到当前工程目录
添加库包含目录
添加库依赖项:SQLite3.lib


函数签名说明

使用的过程根据使用的函数大致分为如下几个过程:

sqlite3_open()
sqlite3_prepare()
sqlite3_step()
sqlite3_column()
sqlite3_finalize()
sqlite3_close()
这几个过程是概念上的说法,而不完全是程序运行的过程,如sqlite3_column()表示的是对查询获得一行里面的数据的列的各个操作统称,实际上在sqlite中并不存在这个函数。

1.  sqlite3_open():打开数据库

在操作数据库之前,首先要打开数据库。这个函数打开一个sqlite数据库文件的连接并且返回一个数据库连接对象。这个操作同时程序中的第一个调用的sqlite函数,同时也是其他sqlite api的先决条件。许多的sqlite接口函数都需要一个数据库连接对象的指针作为它们的第一个参数。
nt sqlite3_open(

  const char *filename,   /* Database filename (UTF-8) */

  sqlite3 **ppDb          /* OUT: SQLite db handle */

);

int sqlite3_open16(

  const void *filename,   /* Database filename (UTF-16) */

  sqlite3 **ppDb          /* OUT: SQLite db handle */

);

int sqlite3_open_v2(

  const char *filename,   /* Database filename (UTF-8) */

  sqlite3 **ppDb,         /* OUT: SQLite db handle */

  int flags,              /* Flags */

  const char *zVfs        /* Name of VFS module to use */

);

 

说明:

假如这个要被打开的数据文件不存在,则一个同名的数据库文件将被创建。如果使用sqlite3_open和sqlite3_open_v2的话,数据库将采用UTF-8的编码方式,sqlite3_open16采用UTF-16的编码方式

返回值:

如果sqlite数据库被成功打开(或创建),将会返回SQLITE_OK,否则将会返回错误码。Sqlite3_errmsg()或者sqlite3_errmsg16可以用于获得数据库打开错误码的英文描述,这两个函数定义为:

const char *sqlite3_errmsg(sqlite3*);

const void *sqlite3_errmsg16(sqlite3*);
参数说明:

filename:需要被打开的数据库文件的文件名,在sqlite3_open和sqlite3_open_v2中这个参数采用UTF-8编码,而在sqlite3_open16中则采用UTF-16编码

ppDb:一个数据库连接句柄被返回到这个参数,即使发生错误。唯一的一场是如果sqlite不能分配内存来存放sqlite对象,ppDb将会被返回一个NULL值。

flags:作为数据库连接的额外控制的参数,可以是SQLITE_OPEN_READONLY,SQLITE_OPEN_READWRITE和SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE中的一个,用于控制数据库的打开方式,可以和SQLITE_OPEN_NOMUTEX,SQLITE_OPEN_FULLMUTEX, SQLITE_OPEN_SHAREDCACHE,以及SQLITE_OPEN_PRIVATECACHE结合使用,具体的详细情况可以查阅文档
2.  Sqlite3_prepare()

这个函数将sql文本转换成一个准备语句(prepared statement)对象,同时返回这个对象的指针。这个接口需要一个数据库连接指针以及一个要准备的包含SQL语句的文本。它实际上并不执行(evaluate)这个SQL语句,它仅仅为执行准备这个sql语句

int sqlite3_prepare(

  sqlite3 *db,            /* Database handle */

  const char *zSql,       /* SQL statement, UTF-8 encoded */

  int nByte,              /* Maximum length of zSql in bytes. */

  sqlite3_stmt **ppStmt,  /* OUT: Statement handle */

  const char **pzTail     /* OUT: Pointer to unused portion of zSql */

);

int sqlite3_prepare_v2(

  sqlite3 *db,            /* Database handle */

  const char *zSql,       /* SQL statement, UTF-8 encoded */

  int nByte,              /* Maximum length of zSql in bytes. */

  sqlite3_stmt **ppStmt,  /* OUT: Statement handle */

  const char **pzTail     /* OUT: Pointer to unused portion of zSql */

);
参数:

db:数据指针

zSql:sql语句,使用UTF-8编码

nByte:如果nByte小于0,则函数取出zSql中从开始到第一个0终止符的内容;如果nByte不是负的,那么它就是这个函数能从zSql中读取的字节数的最大值。如果nBytes非负,zSql在第一次遇见’/000/或’u000’的时候终止

pzTail:上面提到zSql在遇见终止符或者是达到设定的nByte之后结束,假如zSql还有剩余的内容,那么这些剩余的内容被存放到pZTail中,不包括终止符

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

如果执行成功,则返回SQLITE_OK,否则返回一个错误码。推荐在现在任何的程序中都使用sqlite3_prepare_v2这个函数,sqlite3_prepare只是用于前向兼容

 

备注

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

typedef struct sqlite3_stmt sqlite3_stmt;

        

准备语句(prepared statement)对象一个代表一个简单SQL语句对象的实例,这个对象通常被称为“准备语句”或者“编译好的SQL语句”或者就直接称为“语句”。
   语句对象的生命周期经历这样的过程:

l  使用sqlite3_prepare_v2或相关的函数创建这个对象

l  使用sqlite3_bind_*()给宿主参数(host parameters)绑定值

l  通过调用sqlite3_step一次或多次来执行这个sql

l  使用sqlite3——reset()重置这个语句,然后回到第2步,这个过程做0次或多次

l  使用sqlite3_finalize()销毁这个对象

 

在sqlite中并没有定义sqlite3_stmt这个结构的具体内容,它只是一个抽象类型,在使用过程中一般以它的指针进行操作,而sqlite3_stmt类型的指针在实际上是一个指向Vdbe的结构体得指针
<2>宿主参数(host parameters)

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

l  ?

l  ?NNN,NNN代表数字

l  :VVV,VVV代表字符

l  @VVV

l  $VVV

在上面这些模板中,NNN代表一个数字,VVV代表一个字母数字标记符(例如:222表示名称为222的标记符),sql语句中的参数(变量)通过上面的几个模板来指定,如

“select ? from ? “这个语句中指定了两个参数,sqlite语句中的第一个参数的索引值是1,这就知道这个语句中的两个参数的索引分别为1和2,使用”?”的话会被自动给予索引值,而使用”?NNN”则可以自己指定参数的索引值,它表示这个参数的索引值为NNN。”:VVV”表示一个名为”VVV”的参数,它也有一个索引值,被自动指定。

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

这个过程用于执行有前面sqlite3_prepare创建的准备语句。这个语句执行到结果的第一行可用的位置。继续前进到结果的第二行的话,只需再次调用sqlite3_setp()。继续调用sqlite3_setp()知道这个语句完成,那些不返回结果的语句(如:INSERT,UPDATE,或DELETE),sqlite3_step()只执行一次就返回

函数定义

int sqlite3_step(sqlite3_stmt*);

返回值
函数的返回值基于创建sqlite3_stmt参数所使用的函数,假如是使用老版本的接口sqlite3_prepare()和sqlite3_prepare16(),返回值会是 SQLITE_BUSY, SQLITE_DONE, SQLITE_ROW, SQLITE_ERROR 或 SQLITE_MISUSE,而v2版本的接口sqlite3_prepare_v2()和sqlite3_prepare16_v2()则会同时返回这些结果码和扩展结果码。

对所有V3.6.23.1以及其前面的所有版本,需要在sqlite3_step()之后调用sqlite3_reset(),在后续的sqlite3_ step之前。如果调用sqlite3_reset重置准备语句失败,将会导致sqlite3_ step返回SQLITE_MISUSE,但是在V3. 6.23.1以后,sqlite3_step()将会自动调用sqlite3_reset。

int sqlite3_reset(sqlite3_stmt *pStmt);

sqlite3_reset用于重置一个准备语句对象到它的初始状态,然后准备被重新执行。所有sql语句变量使用sqlite3_bind*绑定值,使用sqlite3_clear_bindings重设这些绑定。Sqlite3_reset接口重置准备语句到它代码开始的时候。sqlite3_reset并不改变在准备语句上的任何绑定值,那么这里猜测,可能是语句在被执行的过程中发生了其他的改变,然后这个语句将它重置到绑定值的时候的那个状态。

4. sqlite3_column()

这个过程从执行sqlite3_step()执行一个准备语句得到的结果集的当前行中返回一个列。每次sqlite3_step得到一个结果集的列停下后,这个过程就可以被多次调用去查询这个行的各列的值。对列操作是有多个函数,均以sqlite3_column为前缀

const void sqlite3_column_blob(sqlite3_stmt, int iCol);

int sqlite3_column_bytes(sqlite3_stmt*, int iCol);

int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);

double sqlite3_column_double(sqlite3_stmt*, int iCol);

int sqlite3_column_int(sqlite3_stmt*, int iCol);

sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);

const unsigned char sqlite3_column_text(sqlite3_stmt, int iCol);

const void sqlite3_column_text16(sqlite3_stmt, int iCol);

int sqlite3_column_type(sqlite3_stmt*, int iCol);

sqlite3_value sqlite3_column_value(sqlite3_stmt, int iCol);

说明

第一个参数为从sqlite3_prepare返回来的prepared statement对象的指针,第二参数指定这一行中的想要被返回的列的索引。最左边的一列的索引号是0,行的列数可以使用sqlite3_colum_count()获得。

这些过程会根据情况去转换数值的类型,sqlite内部使用sqlite3_snprintf()去自动进行这个转换,下面是关于转换的细节表:

内部类型请求的类型转换
NULLINTEGER结果是0
NULLFLOAT结果是0.0
NULLTEXT结果是NULL
NULLBLOB结果是NULL
INTEGERFLOAT从整形转换到浮点型
INTEGERTEXT整形的ASCII码显示
INTEGERBLOB同上
FLOATINTEGER浮点型转换到整形
FLOATTEXT浮点型的ASCII显示
FLOATBLOB同上
TEXTINTEGER使用atoi()
TEXTFLOAT使用atof()
TEXTBLOB没有转换
BLOBINTEGER先到TEXT,然后使用atoi
BLOBFLOAT先到TEXT,然后使用atof
BLOBTEXT如果需要的话添加0终止符

注:BLOB数据类型是指二进制的数据块,比如要在数据库中存放一张图片,这张图片就会以二进制形式存放,在sqlite中对应的数据类型就是BLOB

int sqlite3_column_bytes(sqlite3_stmt*, int iCol)int sqlite3_column_bytes16(sqlite3_stmt*, int iCol)两个函数返回对应列的内容的字节数,这个字节数不包括后面类型转换过程中加上的0终止符。

下面是几个最安全和最简单的使用策略

  • 先sqlite3_column_text() ,然后 sqlite3_column_bytes()
  • 先sqlite3_column_blob(),然后sqlite3_column_bytes()
  • 先sqlite3_column_text16(),然后sqlite3_column_bytes16()

5. sqlite3_finalize

​ int sqlite3_finalize(sqlite3_stmt *pStmt);

这个过程销毁前面被sqlite3_prepare创建的准备语句,每个准备语句都必须使用这个函数去销毁以防止内存泄露。

在空指针上调用这个函数没有什么影响,同时可以准备语句的生命周期的任一时刻调用这个函数:在语句被执行前,一次或多次调用sqlite_reset之后,或者在sqlite3_step任何调用之后不管语句是否完成执行

6. sqlite3_close

这个过程关闭前面使用sqlite3_open打开的数据库连接,任何与这个连接相关的准备语句必须在调用这个关闭函数之前被释放

例子

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#include<sqlite3.h>
static int callback(void *NoUsed, int argc, char **argv, char **axColName)
{
	int i;
	for (i = 0; i < argc; i++)
	{
		printf("%s=%s\n", axColName[i], argv[i] ? argv[i] : "NULL");

	}
	printf("\n");
	return 0;
}
#define CHECK_RC(rc,szInfo,szErrMsg) if(rc!=SQLITE_OK)\
{printf("%s error!\n", szInfo);\
printf("%s\n",szErrMsg);\
sqlite3_free(szErrMsg);\
sqlite3_close(db);\
return 0; }
void testsqlite3()
{
	sqlite3 *db = NULL;
	char *szErrMsg = NULL;
	int rc;
	//打开数据库
	rc = sqlite3_open("test.db", &db);
	if (rc)
	{
		fprintf(stderr, "Can't open database:%s\n", sqlite3_errmsg(db));
		sqlite3_close(db);//注意
		return;
	}
	rc = sqlite3_exec(db, "create table tb1(one varchar(10),two smallint)", NULL, 0, &szErrMsg);
	if (rc != SQLITE_OK)
	{
		fprintf(stderr, "SQL error:%s\n", szErrMsg);
		sqlite3_free(szErrMsg);//注意这里对zErrMsg的释放
	}
	sqlite3_close(db);//关闭数据库
	

}
//使用举例
//大宏的使用

void test01()
{
	sqlite3 *db;
	char *dbPath = "./test01.db";
	char *szErrMsg = 0;
	//打开数据库链接
	int rc = sqlite3_open(dbPath, &db);
	/*sqlite数据库的使用非常的简单,通过sqlite3_open打开数据库,打开成功后通过sqlite3_exec执行sql语句,最后使用sqlite3_close关闭数据库。*/
	CHECK_RC(rc, "open database", db);
	char *szSql = "create table UserInfo(ID int primary key,UserName char,PassWord char);";
	rc = sqlite3_exec(db, szSql, 0, 0, &szErrMsg);
	CHECK_RC(rc, "create table", szErrMsg, db);
	rc = sqlite3_exec(db, "insert into UserInfo(ID,UserName,PassWord) values(2,'miss wang','654321')", 0, 0, &szErrMsg);
	CHECK_RC(rc, "insert info", szErrMsg, db);
	rc = sqlite3_exec(db, "insert into UserInfo(ID,UserName,PassWord) values(1,'kfgcome','123456')", 0, 0, &szErrMsg);
	CHECK_RC(rc, "insert info", szErrMsg, db);
	szSql = "select * from UserInfo";
	rc = sqlite3_exec(db, szSql, callback, 0, &szErrMsg);
	CHECK_RC(rc, "query values", szErrMsg, db);
	sqlite3_close(db);
	getchar();
	return;
}
int main()
{
	test01();


	system("pause");
	return EXIT_SUCCESS;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zRmT85po-1616918759598)(C:\Users\11066\AppData\Roaming\Typora\typora-user-images\1616914222304.png)]

重点说一下

回调那一行

逐行获取,如果找到一条数据就进行callback
这里执行sql语句用的是sqlite3_exec,它是前面几个函数的封装

 

int sqlite3_exec(

  sqlite3*,                                  /* An open database */

  const char *sql,                           /* SQL to be evaluated */

  int (*callback)(void*,int,char**,char**),  /* Callback function */

  void *,                                    /* 1st argument to callback */

  char **errmsg                              /* Error msg written here */

);

sqlite3_exec是sqlite3_prepare_v2,sqlite3_step()和sqlite3_finalize()的封装,能让程序多次执行sql语句而不要写许多重复的代码。

Sqlite3_exec接口执行0或多个UTF-8编码的,分号分割的sql语句,传到第二个参数中。如果sqlite3_exec的第三个参数回调函数指针不为空,那么它会为每个来自执行的SQL语句的结果行调用(也就是说回调函数会调用多次,上面例子中会返回2个结果行,因而会被执行2次),第4个参数是传给回调函数的第一个参数,如果回调函数指针为空,那么回调不会发生同时结果行被忽略。

如果在执行sql语句中有错误发生,那么当前的语句的执行被停止,后续的语句也被跳过。第五个参数不为空的时候,它被分配内存并写入了错误信息,所以在sqlite3_exec后面需要调用sqlite3_free去释放这个对象以防止内存泄露

 

回调函数:

int (*callback)(void*,int,char**,char**),  /* Callback function */

         第一个参数通过sqlite3_exec的第第四个参数传入的

         第二个参数是结果行的列数

         第三个参数是行中列数据的指针

         第四个参数是行中列名称的指针

linux下部署开发

wget http://www.sqlite.org/sqlite-3.6.16.tar.gz
执行配置脚本,生成相关文件之后使用make命令编译

[zoulei@CentOS sqlite-3.6.16]$ ./configure
[zoulei@CentOS sqlite-3.6.16]$ make
[zoulei@CentOS sqlite-3.6.16]$ sudo make install
————————————————
版权声明:本文为CSDN博主「zouleideboke」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zouleideboke/article/details/73649886

举例

/*********************************************************************************
 *  *      Copyright:  (C) 2017 zoulei
 *   *                  All rights reserved.
 *    *
 *     *       Filename:  insert.c
 *      *    Description:  This file i
 *       *
 *        *        Version:  1.0.0(2017年06月22日)
 *         *         Author:  zoulei <zoulei121@gmail.com>
 *          *      ChangeLog:  1, Release initial version on "2017年06月22日 19时31分12秒"
 *           *
 *            ********************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include "sqlite3.h"
#define _DEBUG_
int main(int argc, char**argv)
{
    sqlite3 *db=NULL;
    int len;
    int i=0;
    int nrow=0;
    int ncolumn = 0;
    char *zErrMsg =NULL;
    char **azResult=NULL; //二维数组存放结果
        char sql[1024] ;
        char sql1[1024];
            char sql2[1024];
    char sql3[1024];
    memset(sql1,0x00,sizeof(sql1));
    memset(sql2,0x00,sizeof(sql2));
    memset(sql,0x00,sizeof(sql));
    memset(sql3,0x00,sizeof(sql3));

    /* 打开数据库 */
    len = sqlite3_open("user",&db);
    if( len )
    {
        /*  fprintf函数格式化输出错误信息到指定的stderr文件流中  */
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));//sqlite3_errmsg(db)用以获得数据库打开错误码的英文描述。
        sqlite3_close(db);
        exit(1);
    }
    else printf("You have opened a sqlite3 database named user successfully!\n");

    /* 创建表 */

    sprintf(sql," CREATE TABLE SensorData(\
                 ID INTEDER PRIMARY KEY,\
                 SensorID INTEGER,\
                 siteNum INTEGER,\
                 Time VARCHAR(12),\
                 SensorParameter REAL\
                 );");
    sqlite3_exec(db,sql,NULL,NULL,&zErrMsg);
#ifdef _DEBUG_
    printf("%s\n",zErrMsg);
    sqlite3_free(zErrMsg);
#endif
    /*插入数据  */
    //char*sql1 ="INSERT INTO 'SensorData'VALUES(NULL,1,2,201430506201,13.5);";

    sprintf(sql1,"INSERT INTO 'SensorData'VALUES(NULL,1,2,201430506201,13.5);");
    sqlite3_exec(db,sql1,NULL,NULL,&zErrMsg);
    //char*sql2 ="INSERT INTO 'SensorData'VALUES(NULL,3,4,201530506302,14.5);";

    sprintf(sql2,"INSERT INTO 'SensorData'VALUES(NULL,3,4,201530506302,14.5);");
    sqlite3_exec(db,sql2,NULL,NULL,&zErrMsg);

    sprintf(sql3,"INSERT INTO 'SensorData'VALUES(NULL,5,6,201630506413,18.6);");
    sqlite3_exec(db,sql3,NULL,NULL,&zErrMsg);

    /* 查询数据 */
    //sql="select *from SensorData";
    memset(sql,0x00,sizeof(sql));
    strcpy(sql,"select * from SensorData");
    sqlite3_get_table( db , sql , &azResult , &nrow , &ncolumn , &zErrMsg );
    printf("nrow=%d ncolumn=%d\n",nrow,ncolumn);
    printf("the result 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 ;";
    memset(sql,0x00,sizeof(sql));
    strcpy(sql,"delete from SensorData where SensorID = 1 ;");
    sqlite3_exec( db , sql , NULL , NULL , &zErrMsg );
#ifdef _DEBUG_
    printf("zErrMsg = %s \n", zErrMsg);
    sqlite3_free(zErrMsg);
#endif

    /* 查询删除后的数据 */
    //sql = "SELECT * FROM SensorData ";
    memset(sql,0x00,sizeof(sql));
    sprintf(sql,"SELECT * FROM SensorData");
    sqlite3_get_table( db , sql , &azResult , &nrow , &ncolumn , &zErrMsg );
    printf( "row:%d column=%d\n " , nrow , ncolumn );
    printf( "After deleting , the result is : \n" );
    for( i=0 ; i<( nrow + 1 ) * ncolumn ; i++ )
    {
        printf( "azResult[%d] = %s\n", i , azResult[i] );
    }
    sqlite3_free_table(azResult);
#ifdef _DEBUG_
    printf("zErrMsg = %s \n", zErrMsg);
    sqlite3_free(zErrMsg);
#endif

    sqlite3_close(db);
    return 0;

}

注意,首次执行的执行出现了段错误,分析之后发现是操作字符串常量引起的,但是为改正错误再次执行的时候成功了,这个就不知道为啥了,
结果将用到的sql语句用格式化写数组的方式代替指针指向字符串的方式才觉得更为稳妥。

以下是部分结果截图

qlite3_free(zErrMsg);
#endif

/* 查询删除后的数据 */
//sql = "SELECT * FROM SensorData ";
memset(sql,0x00,sizeof(sql));
sprintf(sql,"SELECT * FROM SensorData");
sqlite3_get_table( db , sql , &azResult , &nrow , &ncolumn , &zErrMsg );
printf( "row:%d column=%d\n " , nrow , ncolumn );
printf( "After deleting , the result is : \n" );
for( i=0 ; i<( nrow + 1 ) * ncolumn ; i++ )
{
    printf( "azResult[%d] = %s\n", i , azResult[i] );
}
sqlite3_free_table(azResult);

#ifdef DEBUG
printf(“zErrMsg = %s \n”, zErrMsg);
sqlite3_free(zErrMsg);
#endif

sqlite3_close(db);
return 0;

}


注意,首次执行的执行出现了段错误,分析之后发现是操作字符串常量引起的,但是为改正错误再次执行的时候成功了,这个就不知道为啥了,
结果将用到的sql语句用格式化写数组的方式代替指针指向字符串的方式才觉得更为稳妥。


以下是部分结果截图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NmGrHxzy-1616918759604)(C:\Users\11066\AppData\Roaming\Typora\typora-user-images\1616918708532.png)]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值