49.SQLite 数据库 编程

在嵌入式设备的开发中,sqlite数据库是非常常用的,虽然听着很高大上,但是实际开发难度不是很大,主要对它的函数要使用熟练。那么它到底是一个什么东西?

一. 数据库基本概念

数据库是在数据库管理系统管理和控制之下,存放在存储介质上的数据集合。

说的好难理解,其实就是个类似excel一样的东西,方便我们增删改查数据。

 

二. 常用的数据库

大型数据库

Oracle关系数据库(甲骨文产品的市场占有率高)。

IBM 的DB2(第一个具备网上功能的多媒体关系数据库管理系统,跨平台性强)

中型数据库

微软Server数据库(主要支持windows平台)

小型数据库

mySQL 开源关系数据库,但是对于嵌入式还是比较大

说了那么多,就是了解一下就完了,我们嵌入式中就是用SQLite

 

三. sqlite(轻量级的嵌入式数据库)

1. 特性

  • 低内存占用率(全部源码大致3万行c代码,250KB)
  • 跨平台可移植性
  • 多语言支持
  • 支持数据库大小至2TB;
  • 免费开源
  • 比目前流行的大多数数据库对数据的操作要快

这部分是夸自己呢,可以忽略,用它就对了!!

 

2.数据库的使用

上面说了半天,了解下就行了,这节才开始对这个东西的使用。那么这个东西怎么开始呢?

不急,先举个例子。

我们平时都玩电脑,假如你们老板让你统计一下你们公司所有同事的个人信息,姓名,身高啊,体重啊你该怎么做?

这很简单啊首先要在我们的电脑上下载个WPS软件(我是盗版没原装的),然后安装到我的电脑上,然后打开WPS,新建一个excel表格,然后按照姓名,身高,体重等信息填到表格中,依次将每个员工插入,当然也会有信息需要修改的情况,人家离职了你要去的情况等(增删改查),其实我们的数据库的使用过程也是一样的。

说到这,你会说这么简单啊,我都会,不用再学了。

但是人家是轻量级的数据库,哪有什么图形界面让你操作,在我们的Linux下肯定要使用命令来进行操作啊,这多酷。

 

2.1Sqlite的安装(不明白,复习下linux包管理章节)

方法一:本地安装,官网下载安装包放到本地(db文件),然后解压安装sudo dpkg -i *.deb

方法二:在线安装(有网)sudo apt-get install sqlite3

有时还要装两个依赖库:sudo apt-get install libsqlite3-dev

  sudo apt-get install sqlitebrowser

然后进入输入sqlite3,有打印信息输出,说明安装成功。

 

2.2  数据库的命令行操作

注:sqlite中的命令格式分为两种, 

 

第一种系统命令 都以 '.' 开头

此时打开进入sqlite软件,

1>退出,输入 .quit(或者 .exit)

2>查看sqlite支持哪些命令,输入 .help进行查看。

3>显示当前打开的数据库文件  .database

4>显示数据库中所有表名  .tables

5>查看表的结构  .schema  

6>创建一个数据库 (库里面可以建很多表类似于建个文件夹,里面有很多excel表)

sqlite3 student.db  //建了一个名为student的库

 

第二种是sql语句, 都以 ‘;’ 结尾。(sqlite3 数据库的增删改查)

1> 表格创建

create table stuinfo (id integer, name char, score float);

创建了一个名为stuinfo的表格,然后里面有编号,姓名,分数信息(对应表头)

这里面的数据类型,它做了一个对应

他的INTEGER 对应了我们的int.

REAL对应了我们的float

TEXT 对应char

 

2>向表格种插入数据记录(增)

insert into stuinfo values(1001, 'zhangsan', 18, 80);  //第一种插入形式

insert into stuinfo (id, name, score) values(1002, 'lisi', 90); //第二种形式

 

3>删除一条记录(删)

delete from stuinfo where id=1001 and name='zhangsan';

 

4>更新一条记录(改)

update stuinfo set name='wangwu', score = 82 where id=1002;

 

5>查看数据库记录

select * from stuinfo;

select * from stuinfo where score = 80;

select * from stuinfo where score = 80 and name= 'zhangsan';

select name,score from stuinfo;  查询指定的字段

select * from stuinfo where score >= 85 and score < 90;

 

6>增加一列

alter table stuinfo add column address char; //增加一列地址

 

7>删除一列

sqlite种没有删除列操作,如果想删除表A中的一列或者一行,首先通过SQL创建一个临时表,然后把表A中期望保留的数据存储到临时表中,然后把表A删除,再将临时表重命名为A.

create table stu as select id, name from stuinfo; //创建一个stu表将stuinfo中的姓名等信息保留到stu表中。

drop table stuinfo;//删除stuinfo表中的数据

alter table stu rename to stuinfo; //在将stu表重命名为stuinfo

 

8 >数据库表的维护(有了增删改查,其实我们在用excel的时候也注意到了ID自增等的一些操作)

比如我们在使用中ID啊都要求唯一,就需要输入一些关键字进行限定。

 

数据库主键(设置的数据将会是唯一的存在)

PRIMARY KEY

 

自增字段(设置的字段值自动递增)

AUTOONCREMENT

这个关键字只能用于整型(INTEGER)字段

 

2.数据库的编程API

上面我们说了一下在linux下的命令行操作数据库的一些指令,下面说一下它的编程API接口。

只说几个常用的,其他的可以查询sqlite 的API手册

 

1>打开数据库

函数名

int sqlite3_open(const char *filename, sqlite3 **ppDb);

传入参数

filename:

ppDb

数据库名称

指向sqlite句柄的指针

返回值

成功返回0,失败返回错误码(非零值)

 

2>关闭数据库

函数名

int   sqlite3_close(sqlite3 *db);

 

传入参数

db:

指向sqlite句柄的指针

返回值

成功返回0,失败返回错误码

 

3>返回数据库错误信息

函数名

const  char  *sqlite3_errmg(sqlite3 *db);  

   

传入参数

db

指向sqlite句柄的指针

返回值

返回错误信息

 

4>执行SQL语句操作(重点,且常用)

函数名

int sqlite3_exec(sqlite3* db, const char *sql, int (*callback)(void* arg,int,char**,char**),  void * arg,                                  

  char **errmsg                               );

传入参数

db

sql

callback

arg

errmasg

指向sqlite句柄的指针

将要被执行sql语句

回调函数

只有在查询时,才能给回调函数传参

为callback传参用

错误信息指针的地址

返回值

成功返回0,失败返回错误码

                       查询回调函数(帮助在数据库中检索信息)

函数名

int (*callback)(void* arg,int ncolumns ,char** f_value,char** f_name)

传入参数

arg

ncolumns

f_value

f_name

接收sqlite3_exec 传递来的参数

列数

列的地址(指针数组)

列的名称(指针数组)

返回值

成功返回0

 

5>不使用回调函数执行SQL语句

函数名

int   sqlite3_get_table(sqlite3 *db, const  char  *sql,  char ***resultp,  int*nrow,  int *ncolumn, char **errmsg);

 

传入参数

db

sql

resultp

nrow

ncolumn

errmsg

数据库句柄

SQL语句

用来指向sql执行结果的指针

满足条件的记录的数目

每条记录包含的字段数目

错误信息指针的地址

返回值

成功返回0,失败返回错误码

 

下面举个例子,就可以快速应用这些知识点了:

功能:假如我家开了个水果超市,有以下水果,想实现自动化管理,扫描二维码就能知道当前的水果状态,进货几天了,
好久需要再次进货,那些水果畅销,那些水果不畅销,那些水果春夏秋冬的价格波动,好,那么现在我想将
这些信息保存在数据库中,那么我应该怎么做;
提示: 建立一张fruit表,
假如水果有: 苹果,香蕉,梨,橘子,葡萄....(可以自己查一下英文保存到数据库)
水果价格: 苹果 5元/斤 香蕉 3元/斤 梨 3.5元/斤 橘子2.5元/斤 葡萄 8元/斤....
当前存货: 苹果 80斤 香蕉 200斤 梨 50斤 橘子300斤 葡萄 100斤....
超市每天水果都有进货和卖出嘛,水果的价格随着季节和天气也会有波动,顾客也会看一下每天水果的价格的嘛,
所以要求,根据上述提示,利用数据库完成水果店各种水果的增(进货)删(卖出)改(波动)查(看价格)功能。
并将进出货的时间和顾客光顾的时间记录到数据库中保存。

#include <stdio.h>
#include <string.h>
#include <sqlite3.h>

#define DATABASE "shop.db"

//增
void insert_data(sqlite3 *db)
{
	char sql[128]={0};
	char name_temp[32]={0};
	char time_temp[32]={0};
	float price_temp;
	int stock_temp;
	char *errmsg;
	
	printf("请输入水果种类:");
	scanf("%s", name_temp);
	
	printf("请输入价格:");
	scanf("%f", &price_temp);
	
	printf("请输入进货数量:");
	scanf("%d", &stock_temp);
	
	printf("请输入进货时间:");
	scanf("%s", time_temp);
	
	sprintf(sql,"insert into fruit(name,price,stock,nowtime) values('%s',%f,%d,'%s');",name_temp,price_temp,stock_temp,time_temp);
	if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){
			printf("%s\n", errmsg);
	}
	else
	{
		printf("Insert success.\n");
	}
}
//删
void delete_data(sqlite3 *db)
{
	char sql[128]={0};
	char name_temp[32]={0};
	int stock_temp;
	char *errmsg;
	char time_temp[32]={0};
	
	printf("请输入卖出的水果种类:");
	scanf("%s", name_temp);
	
	printf("请输入剩余的数量:");
	scanf("%d", &stock_temp);
	
	printf("请输入出货时间:");
	scanf("%s", time_temp);
	
	sprintf(sql,"update fruit set stock=%d,nowtime='%s' where name= '%s';",stock_temp,time_temp,name_temp);
	if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){
			printf("%s\n", errmsg);
	}
	else
	{
		printf("out success.\n");
	}
}
//改
void updata_data(sqlite3 *db)
{
	char sql[128]={0};
	char name_temp[32]={0};
	float stock_temp;
	char *errmsg;
	
	printf("请输入水果种类:");
	scanf("%s", name_temp);
	printf("请输入最新的价格:");
	scanf("%f", &stock_temp);

	printf("%s\n",name_temp);
	sprintf(sql,"update fruit set price=%f where name= '%s';",stock_temp,name_temp);
	if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){
			printf("%s\n", errmsg);
	}
	else
	{
		printf("updata success.\n");
	}
}
//查
int callback(void *arg, int f_num, char ** f_value, char ** f_name)
{
	int i=0;
	for(i=0;i< f_num;i++){
		printf("%-13s ", f_value[i]);
	}
	putchar(10);
	puts("-----------------------------------------------");
	return 0;
}
void query_data(sqlite3 *db)
{
	char name_temp[32]={0};
	char sql[128] = {0};
	char *errmsg;

	sprintf(sql,"select * from fruit;");
	if(sqlite3_exec(db,sql,callback,NULL,&errmsg) != SQLITE_OK){
		printf("%s\n",errmsg);
	}
}


int main(void)
{
	int temp = 0;
	sqlite3 *db;
	char *errmsg;
	
	//1.打开数据库
	 if(sqlite3_open(DATABASE, &db) != SQLITE_OK){
			printf("%s",sqlite3_errmsg(db)); //打印出错信息
			return -1;
	 }
	 
	//2.创建表 fruit.db
	if(sqlite3_exec(db, "create table if not exists fruit(id integer primary key autoincrement, name text, price real ,stock integer,nowtime text);",NULL,NULL,&errmsg) != SQLITE_OK){
			printf("%s\n",errmsg); //打印出错信息
			return -1;
	}
	 
	while(1){
	//3.打印显示系统表头,提示用户输入相关操作
		printf("****************************************************\n");
		printf("**1:进货  2:出货  3.更新价格  4.价格查询  5.退出**\n");
		printf("****************************************************\n");
		printf("请输入操作值:");
		scanf("%d", &temp);
		
		switch(temp){
			case 1:
				insert_data(db);//进货
				break;
			case 2:
				delete_data(db);//出货
				break;
			case 3:
				updata_data(db);//更新价格
				break;
			case 4:
				query_data(db);//价格查询
				break;
			case 5:
				sqlite3_close(db);//退出
				exit(0);
				break;
			default:
				printf("请输入正确的选项\n");//提示用户重新输入
				break;
		}
	}
	return 0;
}
gcc -o sqlite sqlite_test.c -lsqlite3 进行编译

./sqlite进行执行

结果:

 

遇到的问题:

1.过程中,出现了,编译第一次没问题,编译第二次出现报错,提示重复创建了db文件,同时增加ID自增功能。

sqlite3_exec(db, "create table if not exists fruit(id integer primary key autoincrement, name text, price real ,stock integer);",NULL,NULL,&errmsg)、

 

2.在我们使用updata时也出现了问题。

sprintf(sql,"update fruit set stock= ‘%d‘, where name=‘%s’;",stock_temp,name_temp);

       if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){

                     printf("%s\n", errmsg);

       }

%d后面,多了个’ , ’号,%d不用加引号。

但是还是报错提示 no such column: ‘apple’,但是我的数据库中明明有这个字段啊。

但是我查询Id字段,还是库存字段都可以正常查询到。

问题记录:

通过命令行直接查看

但是为什么name这个字段不能查找成功??

name =’apple’要加一个引号,这些sql指令的规范一定要注意,很容易少引号,多逗号的,多练多熟悉才能更快的发现问题。

 

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值