【1】数据库基本概念

数据(Data)

能够输入计算机并能被计算机程序识别和处理的信息集合数据库 (Database)

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

常用的数据库

1)大型数据库Oracle公司是最早开发关系数据库的厂商之一,其产品支持最广泛的操作系统平台。目前Oracle关系数据库产品的市场占有率名列前茅。IBM 的DB2是第一个具备网上功能的多媒体关系数据库管理系统,支持包Linux在内的一系列平台。中型数据库Server是微软开发的数据库产品,主要支持windows平台。

2)小型数据库mySQL是一个小型关系型数据库管理系统,开发者为瑞典MySQL AB公司,2008年被Sun公司收购,开放源码。

3)基于嵌入式的数据库

基于嵌入式Linux的数据库主要有SQLite, Firebird, Berkeley DB, eXtremeDBFirebird是关系型数据库,功能强大,支持存储过程、SQL兼容等SQLite关系型数据库,体积小,支持ACID事务Berkeley DB中并没有数据库服务器的概念,它的程序库直接链接到应用程序中 eXtremeDB是内存数据库,运行效率高

SQLite3基础

www.sqlite.org

SQLite的源代码是C,其源代码完全开放。SQLite第一个Alpha版本诞生于2000年5月。 他是一个轻量级的嵌入式数据库。

SQLite有以下特性:

  1. 零配置一无需安装和管理配置;

  2. 储存在单一磁盘文件中的一个完整的数据库;

  3. 数据库文件可以在不同字节顺序的机器间自由共享;

  4. 支持数据库大小至2TB;

  5. 足够小,全部源码大致3万行c代码,250KB;

  6. 比目前流行的大多数数据库对数据的操作要快;

安装方式

在线安装方式:

1
2
3
4
5
6
1.确保虚拟机能联网
2.更新更新源
sudo apt-get update 安装软件及开发环境
sudo apt-get install sqlite3 --->sqlite3数据库软件
sudo apt-get install libsqlite3-dev --->sqlite3数据库开发支持库
sudo apt-get install sqlitebrowser --->sqlite3数据库操作软件

安装成功后,终端输入以下指令,判断是否安装成功:

1
sqlite3  my.db

出现下列语句,标识安装成功,版本不一样无所谓,只要出现 sqlite> 即可

1
2
3
4
	SQLite version 3.7.2 		
​ Enter ".help" for instructions
​ Enter SQL statements terminated with a ";"
​ sqlite>

输入 ".quit "退出数据库

1
2
3
4
5
	linux@linux:~$ sqlite3 my.db
​ SQLite version 3.7.2
​ Enter ".help" for instructions
​ Enter SQL statements terminated with a ";" sqlite> .quit
​ linux@linux:~$

【2】sqlite3命令语句

sqlite3不区分大小写;参考网址:https://m.runoob.com/sqlite/

1. sqlite数据库创建

1
2
3
4
5
6
sqlite3 sq.db
如果sq.db存在则直接打开sq.db数据库,如果不存在则先创建再打开;

SQLite version 3.22.0 2018-01-22 18:45:57 版本无所谓
Enter ".help" for usage hints.
sqlite>

2.系统命令

1
2
3
4
5
6
7
系统命令,需要以 . 开头,不需要以 ; 结尾
.quit 退出数据库
.exit 退出数据库
.help 显示帮助信息,获取所有系统命令;

.table 查看当前数据库下的所有表格;
.schema 查看表的结构

3. sql语句

以分号(;)结尾;不区分大小写;

没有char*类型,用char类型代替

记录:是某一行信息

字段:某一列信息

1)创建表格

1
2
3
4
5
6
7
8
create table 表名 (字段名 数据类型, 字段名 数据类型);
create table if not exists 表名 (字段名 数据类型, 字段名 数据类型);

eg:
CREATE TABLE stu (id int, name char, score float);
CREATE TABLE if not exists stu1 (id int, name char, score float);

注意:数据库不支持严格的数据类型检查,数据类型写错了,创建是能够成功的,不会有错误提示;

2)删除表格

1
2
3
4
drop table 表名;

eg:
drop table stu1;

3)插入记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
字符串类型可以使用单引号,也可以使用双引号

1) 全字段插入
insert into 表名 values (数据1, 数据2, 数据3);
eg:
INSERT INTO stu VALUES (2, 'ls', 99);
INSERT INTO stu VALUES (1, "zs", 59);
注意:
1.数据输入的顺序要与创建时候字段的顺序一致;

2) 部分字段插入
insert into 表名 (字段名1, 字段名2) values (数据1, 数据2);
eg:
INSERT INTO stu (id, name) values (9, 'ww');
注意:
1.数据的顺序要与指定的字段名1,字段名2对应;

4)查看记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
.header on      打开表头
.mode column 对齐
在终端输入shell指令:sqlitebrowser sq.db 图形化界面

1) 查看所有记录
select * from 表名;
eg:
SELECT * FROM stu;

2) 查看某几行
select * from 表名 where 限制条件;
逻辑与 and 逻辑或 or
eg:
SELECT * FROM stu WHERE id<3 AND score>90;
SELECT * FROM stu WHERE id<2 OR id>3;

3) 查看某几列
select 字段1, 字段2 from 表名;
select 字段1, 字段2 from 表名 where 限制条件;
eg:
SELECT id, name FROM stu;
SELECT id, name FROM stu WHERE score>90;

5)修改记录

1
2
3
4
5
update 表名 set 字段=数值 where 限制条件;

eg:
UPDATE stu SET score=60 WHERE id=1;
注意:该语句中的where表明去修改指定的记录,如果没有加where,则表明将所有记录的该值都更新

6)删除记录

1
2
3
4
5
delete from 表名 where 限制条件;

eg:
DELETE FROM stu WHERE id=1;
delete from stu; 删除表格中的所有数据;

7)主键(primary key)

1
2
3
4
5
6
7
8
primary key 主键;
create table 表名(字段名 数据类型 primary key, 字段名 数据类型 );
primary key主键:唯一标识表格中的每一条记录;
例如:id字段为主键,当表格中有id==1的记录时,不允许再插入id为1的记录了;
eg:
CREATE TABLE stu (id int PRIMARY KEY, name char, score float);

注意:主键的值必须唯一。每一张表格都应该设置一个主键,而且只能设置一个。

8)拷贝

1
2
3
4
5
6
7
从a中拷贝所有数据到b中:
create table b as select * from a;
从a中拷贝指定字段到b中:
create table b as select 字段,字段,字段 from a;

CREATE TABLE stu1 AS SELECT * FROM stu;
CREATE TABLE stu2 AS SELECT id, name, score FROM stu;

9)增加列

1
2
alter table 表名 add column 字段名 数据类型;
alter table stu add column score int;

10)修改表名

1
2
alter table 旧表名 rename to 新表名;
alter table stu rename to stuinfo;

11)修改字段名(列名)

1
2
3
4
5
6
7
不支持直接修改列名
1.将表重新命名(a改成b)
alter table stuinfo rename to stu;
2.新建修改名字后的表(新建一个a)
create table stuinfo (name char, age1 int, sex char, score int);
3.从旧表b中取出数据,插入到新表a中;
insert into stuinfo select * from stu;

12)删除列

1
2
3
4
5
6
7
不支持直接删除列;
1.创建一个新表b,并复制旧表a需要保留的字段信息;
create table stu as select name, age1, sex from stuinfo;
2.删除旧表a;
drop table stuinfo;
3.修改新表b的名字a;
alter table stu rename to stuinfo;

练习:

1> 创建一个工人信息库,包含工号(主键)、姓名、年龄、薪资。

2> 添加三条工人信息(可以完整信息,也可以非完整信息)

3> 修改某一个工人的薪资(确定的一个)

4> 展示出工资在10000到20000之间的所有工人信息

5> 删除掉指定姓名工人的信息

6> 工厂倒闭,删除整个工人信息库

【3】sqlite3 API

1. 官网

https://www.sqlite.org/index.html

img

2. sqlite3的C - APIs

1
2
3
4
头文件:
#include <sqlite3.h>
编译时候要加上-lsqlite3
gcc a.c -lsqlite3

1)sqlite3_open

1
2
3
4
5
6
7
8
9
int sqlite3_open(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
功能:打开一个数据库,如果数据库不存在,则创建一个数据库
参数1:要打开的数据库的名字,是一个字符串
参数2:数据库操作句柄,是一个二级指针,需要我们传入一级指针的地址,如果打开数据库成功,则数据库指针由该参数返回
返回值:成功返回SQLITE_OK,失败返回一个错误码(非linux的错误码),可以使用sqlite_errmsg来获取错误信息,由sqlite3_errcode返回错误码值
注意:无论打开数据库是否成功,在不使用数据库时都应该使用sqlite3_close将其关闭

2)sqlite3_close

1
2
3
4
int sqlite3_close(sqlite3*);
功能:关闭数据库,断开句柄所拥有的资源
参数:数据库指针
返回值:成功返回SQLITE_OK,失败返回其他错误码

3)sqlite3_errmsg

1
2
3
4
const char *sqlite3_errmsg(sqlite3*);
功能:通过出错的句柄返回错误信息
参数:出错的句柄
返回值:对应的错误信息,是一个字符串

4)sqlite3_errcode

1
2
3
4
int sqlite3_errcode(sqlite3 *db)
功能:通过错误句柄返回错误码
参数:错误句柄
返回值:错误码

5)sqlite3_exec

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int sqlite3_exec(
sqlite3* db, /* An open database */
const char *sql, /* SQL to be evaluated */
int (*callback)(void*,int,char**,char**), /* Callback function */
void *arg, /* 1st argument to callback */
char **errmsg /* Error msg written here */
);
功能:调用该函数,执行sql语句
参数1:已经被打开的数据库句柄
参数2:要执行的sql语句
参数3:回调函数,主要用于数据库查找时,处理查找的结果集的函数,如果不需要处理sql语句的结果,则填NULL即可
参数4:参数3的第一个参数
参数5:错误信息
返回值:成功返回SQLITE_OK,失败返回其他错误码

6)回调函数

1
2
3
4
5
6
7
int callback(void* arg,int cols,char** value_text,char** value_name)
功能:对执行sql语句后的每一条记录,执行该函数,函数功能可以由用户自定义
参数1:主调函数传递的参数,就是sqlite3_exec的第四个参数,该参数可以用于主调函数和回调函数之间数据交流
参数2:记录查询结果的列的个数
参数3:查询结果数据的起始地址
参数4:查询结果的表头的起始地址
返回值:成功返回0,失败返回错误码

img

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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#include<myhead.h>

//定义添加数据函数
int do_add(sqlite3 *ppDb)
{
//准备sql语句
int add_numb; //学号
char add_name[20]; //姓名
char add_sex[10]; //性别
double add_score; //成绩

printf("请输入要添加的学号:");
scanf("%d", &add_numb);
printf("请输入要添加的姓名:");
scanf("%s", add_name);
printf("请输入要添加的性别:");
scanf("%s", add_sex);
printf("请输入要添加的成绩:");
scanf("%lf", &add_score);
getchar();

char sql[128] = "";
sprintf(sql, "insert into Worker(numb,name,sex,score) values(%d,\"%s\",\"%s\",%.2lf);", add_numb,add_name,add_sex,add_score);
printf("sql = %s\n", sql);

//执行sql语句
char* errmsg = NULL;
if(sqlite3_exec(ppDb, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("sqlite3_exec error: %s\n", errmsg);
//释放errmsg的空间
sqlite3_free(errmsg);
errmsg = NULL;
return -1;
}

printf("插入成功\n");

return 0;

}


//定义查询函数的回调函数
int callback(void *arg, int cols, char**value_text, char **value_name)
{


if((*(int *)arg) == 0)
{
//输出表头
for(int i=0; i<cols; i++)
{
printf("%-10s", value_name[i]);
}
printf("\n");
*((int *)arg) = 1; //更改标识位
}

//输出当前记录的信息
for(int i=0; i<cols; i++)
{
printf("%-10s", value_text[i]);
}
printf("\n");

return 0;
}

//定义查询函数
int do_search(sqlite3 *ppDb)
{

int flag = 0; //标识位

//准备sql语句
char sql[128] = "select * from Worker";
char *errmsg = NULL;

//执行sql语句
if(sqlite3_exec(ppDb, sql, callback, &flag, &errmsg)!=SQLITE_OK)
{
printf("sqlite3_exec error:%s", errmsg);
sqlite3_free(errmsg);
return -1;
}

printf("查询成功\n");


return 0;
}












/*********************************主程序******************************************/
int main(int argc, const char *argv[])
{
//1、打开或创建数据库
sqlite3 *ppDb = NULL;
if( sqlite3_open("./worker.db", &ppDb) != SQLITE_OK)
{
printf("sqlite3_open error,errcode = %d, errmsg = %s\n", sqlite3_errcode(ppDb), sqlite3_errmsg(ppDb));
return -1;
}
printf("sqlite3_open success\n");


//2、数据库相关操作
//2.1 创建数据表
//准备sql语句
//char *sql = "create table if not exists Worker(numb int, name char, sex char, score double);";
char sql[128] = "create table if not exists Worker(numb int, name char, sex char, score double);";
char *errmsg = NULL; //记录返回的错误信息
//执行sql语句
if(sqlite3_exec(ppDb, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("sqlite3_exec error: %s\n", errmsg);
//释放errmsg的空间
sqlite3_free(errmsg);
errmsg = NULL;
return -1;
}
printf("create table success\n");

//2.2数据库增删改查操作
int menu = -1; //菜单选项
while(1)
{
system("clear"); //将上面的内容清屏
printf("\t\t======***公司员工管理系统=======\n");
printf("\t\t======1、增=======\n");
printf("\t\t======2、删=======\n");
printf("\t\t======3、改=======\n");
printf("\t\t======4、查=======\n");
printf("\t\t======0、退出=======\n");
printf("请输入待办业务选项:");
scanf("%d", &menu);
getchar(); //吸收scanf的回车

switch(menu)
{
case 1:
{
//执行增加操作
do_add(ppDb);
}
break;
case 2:
{
//执行删除操作
//do_delete(); //可以根据用户输入的学号进行删除
}
break;
case 3:
{
//执行修改操作
//do_update(); //可以通过用户输入的姓名更改某个记录的信息
}
break;
case 4:
{
//执行查找操作
do_search(ppDb);
}
break;
case 0: goto END;
default:printf("您输入的功能有误,请重新输入!!!!\n");
}

printf("输入任意键,按回车结束\n");
while(getchar() != '\n');
}

END:

//3、关闭数据库
sqlite3_close(ppDb);


return 0;
}

7)sqlite3_get_table

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 */
);
功能:通过执行sql语句,得到结果集中的内容
参数1:数据库句柄
参数2:要执行的sql语句
参数3:查询的结果,需要定义一个二级指针变量,将地址进行传递
参数4: 查询结果的行数
参数5:查询结果的列数
参数6:错误信息
返回值:成功返回SQLITE_OK,失败返回非0的错误码

8)sqltie3_free_table

1
2
3
void sqlite3_free_table(char **result);
功能:释放表的空间
参数:通过sql语句查询的结果
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
#include<myhead.h>

//定义添加数据函数
int do_add(sqlite3 *ppDb)
{
//准备sql语句
int add_numb; //学号
char add_name[20]; //姓名
char add_sex[10]; //性别
double add_score; //成绩

printf("请输入要添加的学号:");
scanf("%d", &add_numb);
printf("请输入要添加的姓名:");
scanf("%s", add_name);
printf("请输入要添加的性别:");
scanf("%s", add_sex);
printf("请输入要添加的成绩:");
scanf("%lf", &add_score);
getchar();

char sql[128] = "";
sprintf(sql, "insert into Worker(numb,name,sex,score) values(%d,\"%s\",\"%s\",%.2lf);", add_numb,add_name,add_sex,add_score);
printf("sql = %s\n", sql);

//执行sql语句
char* errmsg = NULL;
if(sqlite3_exec(ppDb, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("sqlite3_exec error: %s\n", errmsg);
//释放errmsg的空间
sqlite3_free(errmsg);
errmsg = NULL;
return -1;
}

printf("插入成功\n");

return 0;

}


//定义查询函数的回调函数
int callback(void *arg, int cols, char**value_text, char **value_name)
{


if((*(int *)arg) == 0)
{
//输出表头
for(int i=0; i<cols; i++)
{
printf("%-10s", value_name[i]);
}
printf("\n");
*((int *)arg) = 1; //更改标识位
}

//输出当前记录的信息
for(int i=0; i<cols; i++)
{
printf("%-10s", value_text[i]);
}
printf("\n");

return 0;
}

//定义查询函数
int do_search(sqlite3 *ppDb)
{

int flag = 0; //标识位

//准备sql语句
char sql[128] = "select * from Worker";
char *errmsg = NULL;

//执行sql语句
if(sqlite3_exec(ppDb, sql, callback, &flag, &errmsg)!=SQLITE_OK)
{
printf("sqlite3_exec error:%s", errmsg);
sqlite3_free(errmsg);
return -1;
}

printf("查询成功\n");


return 0;
}


//定义查询函数使用get_table函数
int do_search_table(sqlite3 *ppDb)
{
//准备sql语句
char sql[128] = "select * from Worker";
char **res_ptr = NULL; //接收结果集的起始地址
int rows = 0; //接收行数
int cols = 0; //接收列数
char *errmsg = NULL; //接收错误信息

//调用函数执行sql语句并获取结果集
if(sqlite3_get_table(ppDb, sql, &res_ptr, &rows, &cols, &errmsg) != SQLITE_OK)
{
printf("sqlite3_get_table error:%s\n", errmsg);
sqlite3_free(errmsg);
return -1;
}

//至此,res_ptr就是结果集的起始地址,结果集一共有rows行(不包含表头),cols列
for(int i=0; i<rows+1; i++) //外行
{
for(int j=0; j<cols; j++) //内列
{
//输出当前位置的内容
printf("%10s", *(res_ptr + (i*cols+j))); //输出每一个元素值

}
printf("\n"); //每隔一行进行换行
}

//释放结果集
sqlite3_free_table(res_ptr);

return 0;
}










/*********************************主程序******************************************/
int main(int argc, const char *argv[])
{
//1、打开或创建数据库
sqlite3 *ppDb = NULL;
if( sqlite3_open("./worker.db", &ppDb) != SQLITE_OK)
{
printf("sqlite3_open error,errcode = %d, errmsg = %s\n", sqlite3_errcode(ppDb), sqlite3_errmsg(ppDb));
return -1;
}
printf("sqlite3_open success\n");


//2、数据库相关操作
//2.1 创建数据表
//准备sql语句
//char *sql = "create table if not exists Worker(numb int, name char, sex char, score double);";
char sql[128] = "create table if not exists Worker(numb int, name char, sex char, score double);";
char *errmsg = NULL; //记录返回的错误信息
//执行sql语句
if(sqlite3_exec(ppDb, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("sqlite3_exec error: %s\n", errmsg);
//释放errmsg的空间
sqlite3_free(errmsg);
errmsg = NULL;
return -1;
}
printf("create table success\n");

//2.2数据库增删改查操作
int menu = -1; //菜单选项
while(1)
{
system("clear"); //将上面的内容清屏
printf("\t\t======***公司员工管理系统=======\n");
printf("\t\t======1、增=======\n");
printf("\t\t======2、删=======\n");
printf("\t\t======3、改=======\n");
printf("\t\t======4、查=======\n");
printf("\t\t======0、退出=======\n");
printf("请输入待办业务选项:");
scanf("%d", &menu);
getchar(); //吸收scanf的回车

switch(menu)
{
case 1:
{
//执行增加操作
do_add(ppDb);
}
break;
case 2:
{
//执行删除操作
//do_delete(); //可以根据用户输入的学号进行删除
}
break;
case 3:
{
//执行修改操作
//do_update(); //可以通过用户输入的姓名更改某个记录的信息
}
break;
case 4:
{
//执行查找操作
//do_search(ppDb);
do_search_table(ppDb); //查询结果
}
break;
case 0: goto END;
default:printf("您输入的功能有误,请重新输入!!!!\n");
}

printf("输入任意键,按回车结束\n");
while(getchar() != '\n');
}

END:

//3、关闭数据库
sqlite3_close(ppDb);


return 0;
}

本章完